PluginProbe
Translate and Go multilingual – Automatic AI translation – wpLingua / 1.0.3
Translate and Go multilingual – Automatic AI translation – wpLingua v1.0.3
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.3, at inc/translate.php

509 lines 10.4 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 return $json_decoded;
81 }
82
83 /**
84 * Parse each JSON elements
85 */
86 foreach ( $json_decoded as $key => $value ) {
87
88 /**
89 * Don't parse element if it's exclude
90 */
91 if ( in_array( array_merge( $parents, array( $key ) ), $json_excluded ) ) {
92 continue;
93 }
94
95 if ( is_array( $value ) ) {
96
97 /**
98 * If element is an array, parse it
99 */
100 $array_translated[ $key ] = wplng_translate_json_array(
101 $value,
102 $translations,
103 array_merge( $parents, array( $key ) )
104 );
105
106 } elseif ( is_string( $value ) ) {
107
108 /**
109 * If element is a string
110 */
111
112 if ( wplng_str_is_locale_id( $value ) ) {
113
114 /**
115 * If is a local ID (fr_FR, fr, FR, ...), replace by current
116 */
117
118 $array_translated[ $key ] = wplng_get_language_current_id();
119
120 } elseif ( wplng_str_is_html( $value ) ) {
121
122 /**
123 * If element is a HTML, parse and translate it
124 */
125
126 $array_translated[ $key ] = wplng_translate_html(
127 $value,
128 '',
129 '',
130 $translations
131 );
132
133 } elseif ( wplng_str_is_json( $value ) ) {
134
135 /**
136 * If element is a JSON, parse and translate it
137 */
138
139 $array_translated[ $key ] = wplng_translate_json(
140 $value,
141 $translations,
142 array_merge( $parents, [ $key ] )
143 );
144
145 } elseif ( wplng_str_is_url( $value ) ) {
146
147 /**
148 * If element is an URL, replace by translated URL
149 */
150
151 $array_translated[ $key ] = wplng_url_translate( $value );
152
153 } else {
154
155 /**
156 * Element is a unknow string, check if it's translatable
157 * - Check if is an excluded element
158 * - Check if is an included element
159 * - Check if is a translatable string
160 */
161
162 $is_translatable = wplng_json_element_is_translatable(
163 $value,
164 array_merge( $parents, array( $key ) )
165 );
166
167 if ( true === WPLNG_LOG_JSON_DEBUG ) {
168 error_log(
169 var_export(
170 array(
171 'title' => 'wpLingua JSON debug - Parsed value',
172 'parents' => array_merge( $parents, array( $key ) ),
173 'value' => $value,
174 'translatable' => $is_translatable,
175 ),
176 true
177 )
178 );
179 }
180
181 if ( ! $is_translatable ) {
182 continue;
183 }
184
185 $array_translated[ $key ] = wplng_get_translated_text_from_translations(
186 $value,
187 $translations
188 );
189
190 }
191 }
192
193 if ( true === WPLNG_LOG_JSON_DEBUG
194 && ( $array_translated[ $key ] != $json_decoded[ $key ] )
195 && ! is_array( $json_decoded[ $key ] )
196 ) {
197 error_log(
198 var_export(
199 array(
200 'title' => 'wpLingua JSON debug - Compare JSON',
201 'parents' => $parents,
202 'value' => $json_decoded[ $key ],
203 'translated' => $array_translated[ $key ],
204 ),
205 true
206 )
207 );
208 }
209 }
210
211 return $array_translated;
212 }
213
214
215 /**
216 * wpLingua translate : Get translated JSON
217 *
218 * @param string $json
219 * @param array $translations
220 * @param array $parents
221 * @return string
222 */
223 function wplng_translate_json( $json, $translations, $parents = array() ) {
224
225 $json_translated = '';
226 $json_decoded = json_decode( $json, true );
227
228 if ( empty( $json_decoded ) || ! is_array( $json_decoded ) ) {
229 return $json;
230 }
231
232 $json_translated = wp_json_encode(
233 wplng_translate_json_array(
234 $json_decoded,
235 $translations,
236 $parents
237 )
238 );
239
240 if ( empty( $json_translated ) ) {
241 return $json;
242 }
243
244 return $json_translated;
245 }
246
247
248 /**
249 * wpLingua translate : Get translated JS
250 *
251 * @param string $js
252 * @param array $translations
253 * @return string
254 */
255 function wplng_translate_js( $js, $translations ) {
256
257 if ( empty( trim( $js ) ) ) {
258 return $js;
259 }
260
261 $json = array();
262
263 preg_match_all(
264 '#var\s(.*)\s?=\s?(\{.*\});#Ui',
265 $js,
266 $json
267 );
268
269 if ( ! empty( $json[1][0] ) && ! empty( $json[2][0] ) ) {
270
271 $var_name = $json[1][0];
272 $var_json = $json[2][0];
273
274 $json_translated = wplng_translate_json(
275 $var_json,
276 $translations,
277 array( $var_name )
278 );
279
280 if ( $var_json != $json_translated ) {
281 $js = str_replace(
282 $var_json,
283 $json_translated,
284 $js
285 );
286 }
287 }
288
289 return $js;
290 }
291
292
293 /**
294 * wpLingua translate : Get translated HTML
295 *
296 * @param string $html
297 * @param string $language_source_id
298 * @param string $language_target_id
299 * @param array $translations
300 * @return string
301 */
302 function wplng_translate_html(
303 $html,
304 $language_source_id = '',
305 $language_target_id = '',
306 $translations = array()
307 ) {
308
309 if ( empty( $html ) ) {
310 return $html;
311 }
312
313 if ( empty( $language_target_id ) ) {
314 $language_target_id = wplng_get_language_current_id();
315 }
316
317 if ( empty( $language_source_id ) ) {
318 $language_source_id = wplng_get_language_website_id();
319 }
320
321 $dom = wplng_sdh_str_get_html( $html );
322
323 if ( empty( $dom ) ) {
324 return $html;
325 }
326
327 /**
328 * Set dir attr on <body> (ltr or rtl)
329 */
330
331 $language_current = wplng_get_language_by_id( $language_target_id );
332
333 if ( ! empty( $language_current['dir'] ) ) {
334 foreach ( $dom->find( 'body' ) as $element ) {
335 $element->{'dir'} = esc_attr( $language_current['dir'] );
336 }
337 }
338
339 /**
340 * Replace languages IDs in attributes
341 */
342
343 // Replace languages IDs in attributes
344 $attr_lang_id_to_replace = wplng_data_attr_lang_id_to_replace();
345 foreach ( $attr_lang_id_to_replace as $attr ) {
346 foreach ( $dom->find( $attr['selector'] ) as $element ) {
347
348 if ( empty( $element->attr[ $attr['attr'] ] ) ) {
349 continue;
350 }
351
352 $lang_id = $element->attr[ $attr['attr'] ];
353
354 if ( ! wplng_str_is_locale_id( $lang_id ) ) {
355 continue;
356 }
357
358 $element->attr[ $attr['attr'] ] = esc_attr( $language_target_id );
359 }
360 }
361
362 // Replace languages IDs in <body> class
363 foreach ( $dom->find( 'body[class]' ) as $element ) {
364
365 $class_array = explode( ' ', $element->class );
366
367 foreach ( $class_array as $key => $class ) {
368 if ( wplng_str_is_locale_id( $class ) ) {
369 $class_array[ $key ] = $language_target_id;
370 } elseif ( 'ltr' === $class || 'rtl' === $class ) {
371 if ( ! empty( $language_current['dir'] ) ) {
372 $class_array[ $key ] = $language_current['dir'];
373 } else {
374 $class_array[ $key ] = 'ltr';
375 }
376 }
377 }
378
379 $class_array[] = 'wplingua-translated';
380 $class_array = array_unique( $class_array ); // Remove duplicate
381 $class_str = '';
382
383 foreach ( $class_array as $key => $class ) {
384 $class_str .= $class . ' ';
385 }
386
387 $class_str = trim( $class_str );
388 $element->class = esc_attr( $class_str );
389 }
390
391 /**
392 * Translate links in attributes
393 */
394
395 $attr_url_to_translate = wplng_data_attr_url_to_translate();
396
397 foreach ( $attr_url_to_translate as $attr ) {
398 foreach ( $dom->find( $attr['selector'] ) as $element ) {
399
400 if ( empty( $element->attr[ $attr['attr'] ] ) ) {
401 continue;
402 }
403
404 $link = sanitize_url( $element->attr[ $attr['attr'] ] );
405
406 $translated_url = wplng_url_translate(
407 $link,
408 $language_target_id
409 );
410
411 $element->attr[ $attr['attr'] ] = esc_url( $translated_url );
412 }
413 }
414
415 /**
416 * If empty translations, return HTML with translated link
417 */
418
419 if ( empty( $translations ) ) {
420 $dom->save();
421 return (string) wplng_sdh_str_get_html( $dom );
422 }
423
424 /**
425 * Find and parse JSON
426 */
427
428 foreach ( $dom->find( 'script[type="application/ld+json"]' ) as $element ) {
429
430 $translated_json = wplng_translate_json(
431 $element->innertext,
432 $translations
433 );
434
435 $element->innertext = esc_js( $translated_json );
436 }
437
438 /**
439 * Find and translate JS
440 */
441
442 foreach ( $dom->find( 'script' ) as $element ) {
443
444 $translated_js = wplng_translate_js(
445 $element->innertext,
446 $translations
447 );
448
449 $element->innertext = wp_strip_all_tags( $translated_js );
450 }
451
452 /**
453 * Parse Node text
454 */
455
456 $node_text_excluded = wplng_data_excluded_node_text();
457
458 foreach ( $dom->find( 'text' ) as $element ) {
459
460 if ( in_array( $element->parent->tag, $node_text_excluded ) ) {
461 continue;
462 }
463
464 $translated_text = wplng_get_translated_text_from_translations(
465 $element->innertext,
466 $translations
467 );
468
469 $element->innertext = esc_html( $translated_text );
470 }
471
472 /**
473 * Parse attr
474 */
475
476 $attr_text_to_translate = wplng_data_attr_text_to_translate();
477
478 foreach ( $attr_text_to_translate as $attr ) {
479 foreach ( $dom->find( $attr['selector'] ) as $element ) {
480
481 if ( empty( $element->attr[ $attr['attr'] ] ) ) {
482 continue;
483 }
484
485 $text = wplng_text_esc( $element->attr[ $attr['attr'] ] );
486
487 if ( ! wplng_text_is_translatable( $text ) ) {
488 continue;
489 }
490
491 $translated_attr = wplng_get_translated_text_from_translations(
492 $text,
493 $translations
494 );
495
496 $element->attr[ $attr['attr'] ] = esc_attr( $translated_attr );
497 }
498 }
499
500 $dom->save();
501 $dom = (string) wplng_sdh_str_get_html( $dom );
502
503 if ( empty( $dom ) ) {
504 return $html;
505 }
506
507 return $dom;
508 }
509