实现在自己网站后台控制shopify页面翻译

 

 

  1 <?php
  2 namespace Cli\Controller;
  3 
  4 use Curl;
  5 use Exception;
  6 use Think\Controller;
  7 use Think\Log;
  8 use Think\Think;
  9 use translate\Baidu;
 10 use translate\Translate;
 11 
 12 class ShopifyTranslateController extends Controller
 13 {
 14     private $_api       = [
 15         //api info ...
 20     ];
 21     private $_logque;
 22     private $_curlLastErr;
 23     private $_storefrontToken   = \'token....\';
 24     private $_rePrefix      = \'ShopifyTranslate\';
 25     private $_redis;
 26     //locale shopLocales
 27     const CHINESE       = \'zh-CN\';
 28     const JAPANESE      = \'ja\';
 29 
 30 
 31     public function __construct()
 32     {
 33         $this->_api[\'authorization\']    = base64_encode( "{$this->_api[\'key\']}:{$this->_api[\'pwd\']}" );
 34         $this->_redis   = getRedis();
 35 
 36     }
 37 
 38     public function test()
 39     {
 40         $list   = M(\'shopifyTranslate\')->where( [\'resourceId\' => \'gid://shopify/OnlineStoreTheme/80042688647\'] )->select();
 41 
 42         $translations   = [];
 43         foreach( $list as $_item ) {
 44             $source     = json_decode( $_item[\'source\'], true );
 45 
 46             $cn         = str_replace("\n", "\\n", addslashes( $_item[\'zh-cn\'] ) );
 47             $ja         = str_replace("\n", "\\n", addslashes( $_item[\'ja\'] ) );
 48 
 49             $translations[]     = [
 50                 \'key\'   => $source[\'key\'],
 51                 \'value\'     => $cn,
 52                 \'locale\'    => "zh-CN",
 53                 \'translatableContentDigest\'     => $source[\'digest\']
 54             ];
 55 
 56             $translations[]     = [
 57                 \'key\'   => $source[\'key\'],
 58                 \'value\'     => $ja,
 59                 \'locale\'    => "ja",
 60                 \'translatableContentDigest\'     => $source[\'digest\']
 61             ];
 62         }
 63 
 64         $chunked        = array_chunk( $translations, 100 );
 65         foreach( $chunked as $_chunk ) {
 66             $_translations       = json_encode( $_chunk );
 67             $data   = <<<EOF
 68 {
 69     "query": "mutation CreateTranslation(\$id: ID!, \$translations: [TranslationInput!]!) { translationsRegister(resourceId: \$id, translations: \$translations) { translations { locale key outdated value } userErrors { field message } } }",
 70     "variables": {
 71         "id": "gid://shopify/OnlineStoreTheme/80042688647",
 72         "translations": $_translations
 73     }
 74 }           
 75 EOF;
 76             $ret    = $this->sendRequest( $data, \'post\', \'graphql.json\', [], false, \'json\' );
 77             var_dump( $ret );
 78         }
 79 
 80         
 81     }
 82 
 83     public function pull()
 84     {
 85 
 86     }
 87 
 88     //第三方翻译。 https://github.com/John-Theo/google-translate-server
 89     public function translate()
 90     {
 91         $list   = M(\'shopifyTranslate\')->field(\'id, en\')->where( \'ja is null\' )->select();
 92         import( \'Lib.Extend.Translate.sdk.Baidu\', dirname( THINK_PATH ) );
 93 
 94         $baidu      = new Baidu();
 95         foreach( $list as $_item ) {
 96 
 97             $up         = [];
 98 
 99             $en     = urlencode( $_item[\'en\'] );
100 
101             $ret = (new Curl())->get( "http://127.0.0.1:30031?to=zh-CN&text={$en}" );
102             $ret    = json_decode( $ret, true );
103             if( !empty( $ret[\'text\'] ) ) {
104                 $up[\'zh-CN\']    = $ret[\'text\'];
105             }else {
106                 $str        = addslashes( $_item[\'en\'] );
107                 $res        = $baidu->run( $str, \'zh\', \'en\' );
108                 $up[\'zh-CN\']    = addslashes( $res );
109             }
110             sleep( 3 );
111 
112             $ret = (new Curl())->get( "http://127.0.0.1:30031?to=ja&text={$en}" );
113             $ret    = json_decode( $ret, true );
114             if( !empty( $ret[\'text\'] ) ) {
115                 $up[\'ja\']    = $ret[\'text\'];
116             }else {
117                 $res        = $baidu->run( $str, \'jp\', \'en\' );
118                 $up[\'ja\']    = addslashes( $res );
119                 sleep(1);
120             }
121             sleep( 3 );
122 
123 
124             M(\'shopifyTranslate\')->where( [\'id\' => $_item[\'id\']] )->save( $up );
125         }
126     }
127 
128     public function setTranslate( $id = 0 )
129     {
130         $this->_setLog( \'setTranslate start\' );
131         
132         //     $list   = M(\'shopifyTranslate\')->where( [\'synch\' => 0, \'ja\' => [\'exp\', \'is not null\']] )->select();
133 
134         // $keys   = [
135         //     \'!\', \'"\', \'#\', \'$\', \'%\', \''\', \'(\', \')\', \'*\', \'+\', \',\', \'-\', \'.\', \'/\', \':\', \';\', \'<\', \'=\', \'>\', \'?\', \'@\', \'[\', \'\\', \']\', \'^\', \'_\', \'`\', \'{\', \'|\', \'}\', \'~\',
136         //     \'⦅\', \'⦆\', \'¢\', \'£\', \'¬\', \' ̄\', \'¦\', \'¥\', \'₩\', \'│\', \'←\', \'↑\', \'→\', \'↓\', \'■\', \'○\',\'“\',\'”\',\'/ \',\' _ \',\' // \'
137         // ];
138         // $values     = [
139         //     \'!\', \'"\', \'#\', \'$\', \'%\', \'\\'\', \'(\', \')\', \'*\', \'+\', \',\', \'-\', \'.\', \'/\', \':\', \';\', \'<\', \'=\', \'>\', \'?\', \'@\', \'[\', \'\\\', \']\', \'^\', \'_\', \'`\', \'{\', \'|\', \'}\', \'~\',
140         //     \'⦅\', \'⦆\', \'¢\', \'£\', \'¬\', \'¯\', \'¦\', \'¥\', \'₩\', \'│\', \'←\', \'↑\', \'→\', \'↓\', \'■\', \'○\',\'"\',\'"\',\'/\',\'_\',\'//\'
141         // ];
142         // foreach( $list as $_item ) {
143         //     $up     = [];
144 
145         //     $up[\'zh-CN\']    = strtr( $_item[\'zh-cn\'], array_combine( $keys, $values ) );
146         //     $up[\'ja\']    = strtr( $_item[\'ja\'], array_combine( $keys, $values ) );
147 
148         //     M(\'shopifyTranslate\')->where( [\'id\' => $_item[\'id\']] )->save($up);
149         // }
150         // die;
151 
152         $list   = M(\'shopifyTranslate\')->where( [\'synch\' => 0, \'ja\' => [\'exp\', \'is not null\'], \'type\' => [\'neq\', \'EMAIL_TEMPLATE\']] )->select();
153         // $list   = M(\'shopifyTranslate\')->where( [\'id\' => $id] )->select();
154 
155         foreach( $list as $_item ) {
156 
157             $source     = json_decode( $_item[\'source\'], true );
158             $cn         = str_replace("\n", "\\n", addslashes( $_item[\'zh-cn\'] ) );
159             $ja         = str_replace("\n", "\\n", addslashes( $_item[\'ja\'] ) );
160 
161             $data   = <<<EOF
162 {
163     "query": "mutation CreateTranslation(\$id: ID!, \$translations: [TranslationInput!]!) { translationsRegister(resourceId: \$id, translations: \$translations) { translations { locale key outdated value } userErrors { field message } } }",
164     "variables": {
165         "id": "{$_item[\'resourceid\']}",
166         "translations": [
167             {
168                 "key": "{$source[\'key\']}",
169                 "value": "{$cn}",
170                 "locale": "zh-CN",
171                 "translatableContentDigest": "{$source[\'digest\']}"
172             },
173             {
174                 "key": "{$source[\'key\']}",
175                 "value": "{$ja}",
176                 "locale": "ja",
177                 "translatableContentDigest": "{$source[\'digest\']}"
178             }
179         ]
180     }
181 }           
182 EOF;
183             $ret    = $this->sendRequest( $data, \'post\', \'graphql.json\', [], false, \'json\' );
184             if( $ret ) {
185                 M(\'shopifyTranslate\')->where( [\'id\' => $_item[\'id\']] )->save([\'synch\' => 1]);
186                 var_dump( $_item[\'id\'] . \' ok ..\' ); 
187                 // return true;
188                 usleep(500);
189             }else {
190                 var_dump( $_item[\'id\'] . \' fail ..\' . $ret );
191                 // return false;
192             }
193         }
194 
195     }
196 
197     public function setToDb()
198     {
199         $types      = $this->getTranslateType();
200         foreach(  $types as $type ) {
201             $this->getTranslatableResources( $type, self::CHINESE );
202             $this->parseDataToDb( $type, self::CHINESE );
203         }
204     }
205 
206     //解析数据入库
207     public function parseDataToDb( $type, $locale )
208     {
209         $this->_setLog( \'parseDataToDb start\' . json_encode( func_get_args() ) );
210         $cacheFile  = DATA_PATH . "ShopifyTranslate:to{$locale}:{$type}";
211         if( !file_exists( $cacheFile ) ) {
212             $this->_setLog( \'err :: 获取原始数据失败\' . json_encode( func_get_args() ), Log::WARN );
213             return false;
214         }
215 
216         $fhandle    = fopen( $cacheFile, \'r+\' );
217         if( !$fhandle ) {
218             $this->_setLog( \'err :: 打开文件失败\' . $cacheFile, Log::WARN );
219             return false;
220         }
221 
222         $preData    = [];
223         $totals     = 0;
224         while( ($line = fgets( $fhandle )) !== false ) { 
225             $ret       = json_decode( $line, true );
226             if( !$ret ) {
227                 $this->_setLog( \'err :: 读取文件异常\' . $cacheFile . \' >>> \' .  $line, Log::WARN );
228                 continue;
229             }
230     
231             
232             if( isset( $ret[\'data\'][\'translatableResources\'][\'edges\'] ) ) {
233                 // $this->_setLog( \'parseDataToDb edges count == \' . count( $ret[\'data\'][\'translatableResources\'][\'edges\']  ) );
234                 foreach( $ret[\'data\'][\'translatableResources\'][\'edges\'] as $edges ) {
235                     $resourceId     = $edges[\'node\'][\'resourceId\'];
236                     // $this->_setLog( \'parseDataToDb edges > translatableContent > count == \' . count( $edges[\'node\'][\'translatableContent\'] ) );
237                     foreach( $edges[\'node\'][\'translatableContent\'] as $node ) {
238                         if( empty( $node[\'value\'] ) ) 
239                             continue;
240 
241                         $preData_key    = md5( $node[\'key\'] . $resourceId );
242                         $preData[$preData_key] = [
243                             \'en\'            => $node[\'value\'],
244                             \'resourceId\'    => $resourceId,
245                             \'en_md5\'        => md5( $node[\'key\'] . $node[\'value\'] . $resourceId . $type ),
246                             \'source\'        => json_encode( $node ),
247                             \'type\'      => $type,
248                         ];
249                         $totals++;
250                     }
251 
252                     // foreach( $edges[\'node\'][\'translations\'] as $node ) {
253                     //     $preData_key    = md5( $node[\'key\'] . $resourceId );
254                     //     if( isset( $preData[$preData_key] ) )
255                     //         $preData[$preData_key][$node[\'locale\']]  = $node[\'value\'];
256                     
257                     // }
258                 }
259             }else {
260                 $this->_setLog( \'err : 解析结果失败...\' . $cacheFile, Log::WARN );
261             }
262 
263         }
264         $this->_setLog( "parseDataToDb totals == {$totals} , preData count == " . count( $preData ), Log::WARN );
265 
266         fclose( $fhandle );
267        
268         $i = 0;
269         foreach( $preData as $_item ) {
270             if( !M(\'shopifyTranslate\')->where( [\'en_md5\' => $_item[\'en_md5\']] )->find()  ) {
271                 echo $i++;
272                 M(\'shopifyTranslate\')->add( $_item );
273             }  
274         }     
275     }
276     
277     //获取原始信息
278     private function getTranslatableResources( $type, $locale, $force = false )
279     {
280         $this->_setLog( \'getTranslatableResources start\' . json_encode( func_get_args() ) );
281 
282         $cacheFile  = DATA_PATH . "ShopifyTranslate:to{$locale}:{$type}";
283         if( $force && file_exists( $cacheFile ) ) 
284             unlink( $cacheFile  );
285         
286         if( !file_exists( $cacheFile ) ) {
287             $hasNextPage    = false;
288             $after  = \'\';
289             do{
290                 $data   = <<<EOF
291     {
292         translatableResources(first: 50, resourceType: {$type} {$after}) {
293             edges {
294                 cursor
295                 node {
296                     resourceId
297                     translatableContent {
298                     key
299                     value
300                     digest
301                     locale
302                     }
303                     translations(locale: "{$locale}") 
304                     {
305                         locale
306                         key
307                         value
308                     }
309                 }
310             }
311             pageInfo {
312                 hasNextPage
313             }
314         }
315     }
316 EOF;
317 
318                 $ret    = $this->sendRequest( $data );
319                 $hasNextPage    = !empty( $ret[\'data\'][\'translatableResources\'][\'pageInfo\'][\'hasNextPage\'] ) ? true : false;
320                 file_put_contents( $cacheFile, json_encode( $ret ) . PHP_EOL, FILE_APPEND );
321                 foreach( $ret[\'data\'][\'translatableResources\'][\'edges\'] as $edges ) {
322                     $after  = ", after: \"{$edges[\'cursor\']}\"";
323                 }
324                 sleep(1);
325             }while( $hasNextPage );
326         }   
327 
328         $this->_setLog( \'getTranslatableResources over ~\' . json_encode( func_get_args() ) );
329     }
330 
331     //get type
332     private function getTranslateType()
333     {
334         $rekey  = $this->_rePrefix . \'::getTranslateType\';
335         $data   = $this->_redis->get( $rekey );
336         if( $data )
337             return json_decode( $data, true );
338 
339         $data   = <<<EOF
340 {
341     __type(name: "TranslatableResourceType") {
342         enumValues {
343         name
344         }
345     }
346 }
347 EOF;
348 
349         $ret    = $this->sendRequest( $data );
350         if( isset( $ret[\'data\'][\'__type\'][\'enumValues\'] ) ) {
351             $data   = [];
352             foreach( $ret[\'data\'][\'__type\'][\'enumValues\'] as $_name ) {
353                 $data[]     = $_name[\'name\'];
354             }
355             $this->_redis->set( $rekey, json_encode( $data ), 86400 );
356             return $data;
357         }else {
358             $this->_setLog( \'err :: 解析结果失败...\' . $ret, Log::WARN );
359         }
360     }
361     
362 
363     
364     private function sendRequest( $data = \'\', $method = \'post\', $urlExtend = \'graphql.json\', $header = [], $needResHeader = false, $contentType = \'graphql\' )
365     {
366         static $tryTimes = 1;
367         $tmpHeader  = [
368             \'Cache-Controller: max-age=0\', 
369             \'Authorization: Basic \' . $this->_api[\'authorization\'],
370             \'X-Shopify-Storefront-Access-Token: \' . $this->_storefrontToken,
371             \'Accept: application/json\',
372         ];
373         if( is_array( $data ) && !empty( $data ) ) {
374             $data   = json_encode( $data );
375             $tmpHeader[]   = \'Content-Length: \' . strlen( $data );
376         }else {
377             $data   = (string)$data;
378         }
379 
380         if( !empty( $header ) ) {
381             $tmpHeader  = array_merge( $tmpHeader, $header );
382         }
383 
384         if( $contentType == \'graphql\' ) {
385             $tmpHeader[]    = \'Content-Type:application/graphql\';
386         }else {
387             $tmpHeader[]    = \'Content-Type:application/\' . $contentType;
388         }
389 
390         $url    = "https://{$this->_api[\'key\']}:{$this->_api[\'pwd\']}@{$this->_api[\'url\']}{$this->_api[\'version\']}/{$urlExtend}";
391         $this->_setLog( \'开始curl \'. $method .\' ,url == \' . $url . \',, param == \' . $data . \',, header == \' . var_export( $tmpHeader, true ) );
392         $ret    = (new Curl())->execute( $method, $url, $data, \'\',  $tmpHeader, \'\', \'\', $needResHeader );
393         if( is_array( $ret ) || $ret === false ) {
394             $tryTimes++;
395             if( $tryTimes >= 1 ) {
396                 $this->_curlLastErr     = "send curl error ..";
397                 if( isset( $ret[1] ) )
398                     $this->_curlLastErr     .= "{$ret[1]}";
399                 $this->_setLog( \'curl 请求shopify失败,请检查! \' . json_encode( $ret ), Log::WARN );
400                 return false;
401             }else {
402                 return $this->sendRequest( $method, $urlExtend, $data, $header, $needResHeader );
403             }
404         }
405 
406         $deRet    = json_decode( $ret, true );
407 
408         if( $needResHeader ) {
409             if( isset( $deRet[\'ret\'][\'errors\'] ) ) {
410                 $this->_curlLastErr     = $ret;
411                 $this->_setLog( \'请求成功,但是返回了失败,.\' . $ret, Log::WARN );
412                 return false;
413             }
414         }else {
415             if( isset( $deRet[\'errors\'] )  || isset( $deRet[\'error\'] ) ) {
416                 $this->_curlLastErr     = $ret;
417                 $this->_setLog( \'请求成功,但是返回了失败,.\' . $ret, Log::WARN );
418                 return false;
419             }
420         }
421 
422         // $this->_setLog( \'请求成功了,\' . $ret  );
423 
424         return $deRet;
425     }
426 
427     public function htmlMof()
428     {
429 
430         header(\'Access-Control-Allow-Origin: *\');
431         header(\'Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept\');
432 
433         if( substr($_POST[\'html\'], 0, 3) == \'<p>\' ) {
434             $_POST[\'html\']  = substr( $_POST[\'html\'], 3 );
435             $_POST[\'html\']  = substr( $_POST[\'html\'], 0, -4 );
436         }
437 
438         $ret    = M(\'shopifyTranslate\')->where([\'id\' => $_POST[\'id\']])->save( [\'ja\' => $_POST[\'html\'],\'mof_time\' => time()] );
439         if( $ret !== false ) {
440             $this->setTranslate( $_POST[\'id\'] );
441             echo json_encode( [\'code\' => 1] );
442         }else 
443             echo json_encode( [\'code\' => 0] );
444         die;
445     }
446 
447     private function _setLog( $msg, $level = Log::NOTICE )
448     {
449         Log::write( $msg . PHP_EOL, Log::NOTICE, \'\', durableLog( \'api-shopify-translate\' ) );
450         return;
451 
452         if( !$this->_logque instanceof \SplQueue )
453             $this->_logque  = new \SplQueue();
454 
455         $this->_logque->enqueue( $msg . PHP_EOL );
456 
457         if( $level == Log::ERR ) {
458             //send mail
459             exit;
460         }
461     }
462 
463     public function __destruct()
464     {
465         if( $this->_logque instanceof \SplQueue ) {
466             $msg        = \'\';
467             while( !$this->_logque->isEmpty() ) {
468                 $msg    .= $this->_logque->dequeue();
469             }
470             Log::write( $msg, Log::NOTICE, \'\', durableLog( \'api-shopify-translate\' ) );
471         }
472     }
473 
474 }

 

版权声明:本文为lxdd原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/lxdd/p/13937538.html