PluginProbe
Translate and Go multilingual – Automatic AI translation – wpLingua / 1.0.4
Translate and Go multilingual – Automatic AI translation – wpLingua v1.0.4
2.16.7 2.16.6 2.16.5 2.16.4 2.16.3 2.16.2 2.16.1 2.16.0 2.15.2 2.15.1 2.15.0 2.14.3 2.14.2 2.14.1 2.14.0 2.13.1 2.13.0 2.12.3 2.12.2 2.12.1 trunk 1.0.3 1.0.4 1.0.5 1.1.0 All 112 releases
wplingua / inc / translate.php

translate.php in Translate and Go multilingual – Automatic AI translation – wpLingua 1.0.4, at inc/translate.php

547 lines 11.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // If this file is called directly, abort.
4 if ( ! defined( 'WPINC' ) ) {
5 die;
6 }
7
8
9 /**
10 * Get the translated text from translations array
11 *
12 * @param string $text
13 * @param array $translations
14 * @return string
15 */
16 function wplng_get_translated_text_from_translations( $text, $translations ) {
17
18 if ( empty( trim( $text ) ) ) {
19 return $text;
20 }
21
22 /**
23 * Get spaces before and after text
24 */
25 $temp = array();
26 $spaces_before = '';
27 $spaces_after = '';
28
29 preg_match( '#^(\s*).*#', $text, $temp );
30 if ( ! empty( $temp[1] ) ) {
31 $spaces_before = $temp[1];
32 }
33
34 preg_match( '#.*(\s*)$#U', $text, $temp );
35 if ( ! empty( $temp[1] ) ) {
36 $spaces_after = $temp[1];
37 }
38
39 $text = wplng_text_esc( $text );
40 $translated = $text;
41
42 if ( wplng_text_is_translatable( $text ) ) {
43 foreach ( $translations as $translation ) {
44
45 if ( ! isset( $translation['source'] ) ) {
46 continue;
47 }
48
49 $source = wplng_text_esc( $translation['source'] );
50
51 if ( $text === $source ) {
52 $translated = $translation['translation'];
53 }
54 }
55 }
56
57 $translated = esc_html( $translated );
58
59 return $spaces_before . $translated . $spaces_after;
60 }
61
62
63 /**
64 * wpLingua translate : Get translated array from decoded JSON
65 *
66 * @param array $json_decoded
67 * @param array $translations
68 * @param array $parents
69 * @return array
70 */
71 function wplng_translate_json_array( $json_decoded, $translations, $parents = array() ) {
72
73 $array_translated = $json_decoded;
74 $json_excluded = wplng_data_excluded_json();
75
76 /**
77 * Don't parse JSON if it's exclude
78 */
79 if ( in_array( $parents, $json_excluded ) ) {
80
81 if ( true === WPLNG_LOG_JSON_DEBUG ) {
82
83 $debug = array(
84 'title' => 'wpLingua JSON debug - Excluded parent',
85 'parents' => $parents,
86 'value' => $json_decoded,
87 );
88
89 error_log(
90 var_export(
91 $debug,
92 true
93 )
94 );
95 }
96
97 return $json_decoded;
98 }
99
100 /**
101 * Parse each JSON elements
102 */
103 foreach ( $json_decoded as $key => $value ) {
104
105 /**
106 * Don't parse element if it's exclude
107 */
108 if ( in_array( array_merge( $parents, array( $key ) ), $json_excluded ) ) {
109
110 if ( true === WPLNG_LOG_JSON_DEBUG ) {
111
112 $debug = array(
113 'title' => 'wpLingua JSON debug - Excluded element',
114 'parents' => array_merge( $parents, array( $key ) ),
115 'value' => $value,
116 );
117
118 error_log(
119 var_export(
120 $debug,
121 true
122 )
123 );
124 }
125
126 continue;
127 }
128
129 if ( is_array( $value ) ) {
130
131 /**
132 * If element is an array, parse it
133 */
134
135 $array_translated[ $key ] = wplng_translate_json_array(
136 $value,
137 $translations,
138 array_merge( $parents, array( $key ) )
139 );
140
141 } elseif ( is_string( $value ) ) {
142
143 $debug_type = '';
144
145 /**
146 * If element is a string
147 */
148
149 if ( wplng_str_is_locale_id( $value ) ) {
150
151 /**
152 * If is a local ID (fr_FR, fr, FR, ...), replace by current
153 */
154
155 $debug_type = 'String - Local ID';
156 $array_translated[ $key ] = wplng_get_language_current_id();
157
158 } elseif ( wplng_str_is_html( $value ) ) {
159
160 /**
161 * If element is a HTML, parse and translate it
162 */
163
164 $debug_type = 'String - HTML';
165 $array_translated[ $key ] = wplng_translate_html(
166 $value,
167 '',
168 '',
169 $translations
170 );
171
172 } elseif ( wplng_str_is_json( $value ) ) {
173
174 /**
175 * If element is a JSON, parse and translate it
176 */
177
178 $debug_type = 'String - JSON';
179 $array_translated[ $key ] = wplng_translate_json(
180 $value,
181 $translations,
182 array_merge( $parents, [ $key ] )
183 );
184
185 } elseif ( wplng_str_is_url( $value ) ) {
186
187 /**
188 * If element is an URL, replace by translated URL
189 */
190
191 $debug_type = 'String - URL';
192 $array_translated[ $key ] = wplng_url_translate( $value );
193
194 } else {
195
196 /**
197 * Element is a unknow string, check if it's translatable
198 * - Check if is an excluded element
199 * - Check if is an included element
200 * - Check if is a translatable string
201 */
202
203 $is_translatable = wplng_json_element_is_translatable(
204 $value,
205 array_merge( $parents, array( $key ) )
206 );
207
208 if ( $is_translatable ) {
209 $debug_type = 'String - Translatale';
210 $array_translated[ $key ] = wplng_get_translated_text_from_translations(
211 $value,
212 $translations
213 );
214 } else {
215 $debug_type = 'String - Untranslatale';
216 }
217 }
218
219 /**
220 * Print debug data in debug.log file
221 */
222
223 if ( true === WPLNG_LOG_JSON_DEBUG
224 && isset( $json_decoded[ $key ] )
225 && isset( $array_translated[ $key ] )
226 ) {
227
228 $debug = array(
229 'title' => 'wpLingua JSON debug',
230 'parents' => array_merge( $parents, array( $key ) ),
231 'type' => $debug_type,
232 'value' => $json_decoded[ $key ],
233 );
234
235 if ( $json_decoded[ $key ] !== $array_translated[ $key ] ) {
236 $debug['translated'] = $array_translated[ $key ];
237 }
238
239 error_log(
240 var_export(
241 $debug,
242 true
243 )
244 );
245 }
246 }
247 }
248
249 return $array_translated;
250 }
251
252
253 /**
254 * wpLingua translate : Get translated JSON
255 *
256 * @param string $json
257 * @param array $translations
258 * @param array $parents
259 * @return string
260 */
261 function wplng_translate_json( $json, $translations, $parents = array() ) {
262
263 $json_translated = '';
264 $json_decoded = json_decode( $json, true );
265
266 if ( empty( $json_decoded ) || ! is_array( $json_decoded ) ) {
267 return $json;
268 }
269
270 $json_translated = wp_json_encode(
271 wplng_translate_json_array(
272 $json_decoded,
273 $translations,
274 $parents
275 )
276 );
277
278 if ( empty( $json_translated ) ) {
279 return $json;
280 }
281
282 return $json_translated;
283 }
284
285
286 /**
287 * wpLingua translate : Get translated JS
288 *
289 * @param string $js
290 * @param array $translations
291 * @return string
292 */
293 function wplng_translate_js( $js, $translations ) {
294
295 if ( empty( trim( $js ) ) ) {
296 return $js;
297 }
298
299 $json = array();
300
301 preg_match_all(
302 '#var\s(.*)\s?=\s?(\{.*\});#Ui',
303 $js,
304 $json
305 );
306
307 if ( ! empty( $json[1][0] ) && ! empty( $json[2][0] ) ) {
308
309 $var_name = $json[1][0];
310 $var_json = $json[2][0];
311
312 $json_translated = wplng_translate_json(
313 $var_json,
314 $translations,
315 array( $var_name )
316 );
317
318 if ( $var_json != $json_translated ) {
319 $js = str_replace(
320 $var_json,
321 $json_translated,
322 $js
323 );
324 }
325 }
326
327 return $js;
328 }
329
330
331 /**
332 * wpLingua translate : Get translated HTML
333 *
334 * @param string $html
335 * @param string $language_source_id
336 * @param string $language_target_id
337 * @param array $translations
338 * @return string
339 */
340 function wplng_translate_html(
341 $html,
342 $language_source_id = '',
343 $language_target_id = '',
344 $translations = array()
345 ) {
346
347 if ( empty( $html ) ) {
348 return $html;
349 }
350
351 if ( empty( $language_target_id ) ) {
352 $language_target_id = wplng_get_language_current_id();
353 }
354
355 if ( empty( $language_source_id ) ) {
356 $language_source_id = wplng_get_language_website_id();
357 }
358
359 $dom = wplng_sdh_str_get_html( $html );
360
361 if ( empty( $dom ) ) {
362 return $html;
363 }
364
365 /**
366 * Set dir attr on <body> (ltr or rtl)
367 */
368
369 $language_current = wplng_get_language_by_id( $language_target_id );
370
371 if ( ! empty( $language_current['dir'] ) ) {
372 foreach ( $dom->find( 'body' ) as $element ) {
373 $element->{'dir'} = esc_attr( $language_current['dir'] );
374 }
375 }
376
377 /**
378 * Replace languages IDs in attributes
379 */
380
381 // Replace languages IDs in attributes
382 $attr_lang_id_to_replace = wplng_data_attr_lang_id_to_replace();
383 foreach ( $attr_lang_id_to_replace as $attr ) {
384 foreach ( $dom->find( $attr['selector'] ) as $element ) {
385
386 if ( empty( $element->attr[ $attr['attr'] ] ) ) {
387 continue;
388 }
389
390 $lang_id = $element->attr[ $attr['attr'] ];
391
392 if ( ! wplng_str_is_locale_id( $lang_id ) ) {
393 continue;
394 }
395
396 $element->attr[ $attr['attr'] ] = esc_attr( $language_target_id );
397 }
398 }
399
400 // Replace languages IDs in <body> class
401 foreach ( $dom->find( 'body[class]' ) as $element ) {
402
403 $class_array = explode( ' ', $element->class );
404
405 foreach ( $class_array as $key => $class ) {
406 if ( wplng_str_is_locale_id( $class ) ) {
407 $class_array[ $key ] = $language_target_id;
408 } elseif ( 'ltr' === $class || 'rtl' === $class ) {
409 if ( ! empty( $language_current['dir'] ) ) {
410 $class_array[ $key ] = $language_current['dir'];
411 } else {
412 $class_array[ $key ] = 'ltr';
413 }
414 }
415 }
416
417 $class_array[] = 'wplingua-translated';
418 $class_array = array_unique( $class_array ); // Remove duplicate
419 $class_str = '';
420
421 foreach ( $class_array as $key => $class ) {
422 $class_str .= $class . ' ';
423 }
424
425 $class_str = trim( $class_str );
426 $element->class = esc_attr( $class_str );
427 }
428
429 /**
430 * Translate links in attributes
431 */
432
433 $attr_url_to_translate = wplng_data_attr_url_to_translate();
434
435 foreach ( $attr_url_to_translate as $attr ) {
436 foreach ( $dom->find( $attr['selector'] ) as $element ) {
437
438 if ( empty( $element->attr[ $attr['attr'] ] ) ) {
439 continue;
440 }
441
442 $link = sanitize_url( $element->attr[ $attr['attr'] ] );
443
444 $translated_url = wplng_url_translate(
445 $link,
446 $language_target_id
447 );
448
449 $element->attr[ $attr['attr'] ] = esc_url( $translated_url );
450 }
451 }
452
453 /**
454 * If empty translations, return HTML with translated link
455 */
456
457 if ( empty( $translations ) ) {
458 $dom->save();
459 return (string) wplng_sdh_str_get_html( $dom );
460 }
461
462 /**
463 * Find and parse JSON
464 */
465
466 foreach ( $dom->find( 'script[type="application/ld+json"]' ) as $element ) {
467
468 $translated_json = wplng_translate_json(
469 $element->innertext,
470 $translations
471 );
472
473 $element->innertext = $translated_json;
474 }
475
476 /**
477 * Find and translate JS
478 */
479
480 foreach ( $dom->find( 'script' ) as $element ) {
481
482 $translated_js = wplng_translate_js(
483 $element->innertext,
484 $translations
485 );
486
487 $element->innertext = $translated_js;
488 }
489
490 /**
491 * Parse Node text
492 */
493
494 $node_text_excluded = wplng_data_excluded_node_text();
495
496 foreach ( $dom->find( 'text' ) as $element ) {
497
498 if ( in_array( $element->parent->tag, $node_text_excluded ) ) {
499 continue;
500 }
501
502 $translated_text = wplng_get_translated_text_from_translations(
503 $element->innertext,
504 $translations
505 );
506
507 $element->innertext = esc_html( $translated_text );
508 }
509
510 /**
511 * Parse attr
512 */
513
514 $attr_text_to_translate = wplng_data_attr_text_to_translate();
515
516 foreach ( $attr_text_to_translate as $attr ) {
517 foreach ( $dom->find( $attr['selector'] ) as $element ) {
518
519 if ( empty( $element->attr[ $attr['attr'] ] ) ) {
520 continue;
521 }
522
523 $text = wplng_text_esc( $element->attr[ $attr['attr'] ] );
524
525 if ( ! wplng_text_is_translatable( $text ) ) {
526 continue;
527 }
528
529 $translated_attr = wplng_get_translated_text_from_translations(
530 $text,
531 $translations
532 );
533
534 $element->attr[ $attr['attr'] ] = esc_attr( $translated_attr );
535 }
536 }
537
538 $dom->save();
539 $dom = (string) wplng_sdh_str_get_html( $dom );
540
541 if ( empty( $dom ) ) {
542 return $html;
543 }
544
545 return $dom;
546 }
547