PluginProbe
Translate and Go multilingual – Automatic AI translation – wpLingua / 2.16.7
Translate and Go multilingual – Automatic AI translation – wpLingua v2.16.7
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
← All changes | inc/dom/load-progress.php +454 -451 2.12.12.16.7 View file →
@@ -1,451 +1,454 @@
1 -<?php
2 -
3 -// If this file is called directly, abort.
4 -if ( ! defined( 'WPINC' ) ) {
5 - die;
6 -}
7 -
8 -
9 -/**
10 - * Modify dom for the "in progress" load mode
11 - *
12 - * @param object $dom
13 - * @param array $args
14 - * @return object
15 - */
16 -function wplng_dom_load_progress( $dom, $args ) {
17 -
18 - wplng_args_setup( $args );
19 -
20 - if ( $args['load'] !== 'progress'
21 - || ! current_user_can( 'edit_posts' )
22 - ) {
23 - return $dom;
24 - }
25 -
26 - /**
27 - * Add effect on unknow texts and translate know texts
28 - */
29 -
30 - $edit_link_excluded = wplng_data_excluded_editor_link();
31 - $node_text_excluded = wplng_data_excluded_node_text();
32 -
33 - foreach ( $dom->find( 'body text' ) as $element ) {
34 -
35 - if ( in_array( $element->parent->tag, $edit_link_excluded )
36 - || in_array( $element->parent->tag, $node_text_excluded )
37 - ) {
38 - continue;
39 - }
40 -
41 - $text = $element->innertext;
42 -
43 - if ( empty( trim( $text ) ) ) {
44 - continue;
45 - }
46 -
47 - // Manage non breaking space
48 - $text = str_replace(
49 - array( '&nbsp;', html_entity_decode( '&nbsp;' ) ),
50 - array( ' ', ' ' ),
51 - $text
52 - );
53 -
54 - /**
55 - * Get spaces before and after text
56 - */
57 -
58 - $temp = array();
59 - $spaces_before = '';
60 - $spaces_after = '';
61 -
62 - preg_match( '/^(\s*).*/', $text, $temp );
63 - if ( ! empty( $temp[1] ) ) {
64 - $spaces_before = $temp[1];
65 - }
66 -
67 - preg_match( '/.*(\s*)$/U', $text, $temp );
68 - if ( ! empty( $temp[1] ) ) {
69 - $spaces_after = $temp[1];
70 - }
71 -
72 - $text = wplng_text_esc( $text );
73 - $translated = '';
74 -
75 - if ( wplng_text_is_translatable( $text ) ) {
76 -
77 - foreach ( $args['translations'] as $translation ) {
78 - if ( $text === $translation['source'] ) {
79 - $translated = $translation['translation'];
80 - break;
81 - }
82 - }
83 -
84 - if ( '' === $translated ) {
85 -
86 - $innertext = '<span';
87 - $innertext .= ' class="wplng-in-progress-text"';
88 - $innertext .= ' title="' . esc_attr__( 'Translation in progress', 'wplingua' ) . '"';
89 - $innertext .= '>';
90 - $innertext .= esc_html( $spaces_before . $text . $spaces_after );
91 - $innertext .= '</span>';
92 -
93 - $element->innertext = $innertext;
94 -
95 - } else {
96 - $element->innertext = esc_html( $spaces_before . $translated . $spaces_after );
97 - }
98 - }
99 - }
100 -
101 - /**
102 - * Create the html of message bar
103 - */
104 -
105 - $number_of_texts = (int) $args['count_texts'];
106 - $numer_of_translated_texts = count( $args['translations'] );
107 -
108 - // Calculate percentage
109 -
110 - $percentage = 0;
111 - if ( $number_of_texts > 0 ) {
112 - $percentage = (int) ( ( $numer_of_translated_texts / $number_of_texts ) * 100 );
113 - }
114 -
115 - if ( $percentage < 1 ) {
116 - $percentage = 1;
117 - }
118 -
119 - // Make the HTML
120 -
121 - $html = '<div id="wplng-in-progress-container">';
122 -
123 - $html .= '<div id="wplng-in-progress-message">';
124 - $html .= '<span class="dashicons dashicons-update wplng-spin"></span> ';
125 -
126 - $html .= '<span class="wplng-in-progress-text-mobile">';
127 - $html .= esc_html__( 'Translation in progress', 'wplingua' );
128 - $html .= '</span>';
129 -
130 - $html .= '<span class="wplng-in-progress-text-desktop">';
131 - $html .= esc_html__( 'In progress: Translation and saving of new texts', 'wplingua' );
132 - $html .= '</span>';
133 -
134 - $html .= ' - ';
135 - $html .= '<span id="wplng-in-progress-percent">';
136 - $html .= esc_html( $percentage );
137 - $html .= '</span>';
138 - $html .= ' %';
139 - $html .= '</div>'; // End #wplng-translation-in-progress
140 -
141 - $html .= '<div id="wplng-progress-bar">';
142 - $html .= '<div';
143 - $html .= ' id="wplng-progress-bar-value"';
144 - $html .= ' style="width: ' . esc_attr( $percentage ) . '%"';
145 - $html .= '>';
146 - $html .= '</div>'; // End #wplng-progress-bar-value
147 - $html .= '</div>'; // End #wplng-progress-bar
148 -
149 - $html .= '<div id="wplng-in-progress-error" style="display: none;">';
150 - $html .= '<span class="dashicons dashicons-info-outline"></span> ';
151 -
152 - $html .= '<span class="wplng-in-progress-text-mobile">';
153 - $html .= esc_html__( 'Error during translation.', 'wplingua' );
154 - $html .= '</span>';
155 -
156 - $html .= '<span class="wplng-in-progress-text-desktop">';
157 - $html .= esc_html__( 'Error during translation. Check the browser console for more information.', 'wplingua' );
158 - $html .= '</span>';
159 -
160 - $html .= '<span';
161 - $html .= ' id="wplng-in-progress-error-close"';
162 - $html .= ' class="dashicons dashicons-no-alt"';
163 - $html .= ' title="' . esc_attr__( 'Close', 'wpLingua' ) . '"';
164 - $html .= '></span>';
165 -
166 - $html .= '</div>'; // End wplng-in-progress-error
167 -
168 - $html .= '</div>'; // End #wplng-in-progress-containe
169 -
170 - /**
171 - * Prepare the texts chunks
172 - */
173 -
174 - $texts_unknow_by_chunk = array();
175 - $current_chunk = array();
176 - $current_chars = 0;
177 - $max_items_per_chunk = (int) ( WPLNG_MAX_TRANSLATIONS_STR / 2 );
178 - $max_chars_per_chunk = (int) ( WPLNG_MAX_TRANSLATIONS_CHAR / 2 );
179 -
180 - foreach ( $args['texts_unknow'] as $text_unknow ) {
181 -
182 - $text = (string) $text_unknow;
183 - $len = function_exists( 'mb_strlen' ) ? mb_strlen( $text, 'UTF-8' ) : strlen( $text );
184 -
185 - // If a single item is longer than allowed, truncate it to fit the limit.
186 - if ( $len > $max_chars_per_chunk ) {
187 - $text = function_exists( 'mb_substr' ) ? mb_substr( $text, 0, $max_chars_per_chunk, 'UTF-8' ) : substr( $text, 0, $max_chars_per_chunk );
188 - $len = $max_chars_per_chunk;
189 - }
190 -
191 - // If adding this text would exceed either limit, flush current chunk.
192 - if ( count( $current_chunk ) >= $max_items_per_chunk || ( $current_chars + $len ) > $max_chars_per_chunk ) {
193 - if ( ! empty( $current_chunk ) ) {
194 - $texts_unknow_by_chunk[] = array(
195 - 'percentage' => (int) ( ( $numer_of_translated_texts / $number_of_texts ) * 100 ),
196 - 'texts' => $current_chunk,
197 - );
198 - $current_chunk = array();
199 - $current_chars = 0;
200 - }
201 - }
202 -
203 - $current_chunk[] = wplng_encryption_encrypt( $text );
204 - $current_chars += $len;
205 - ++$numer_of_translated_texts;
206 - }
207 -
208 - // Push last chunk if any
209 - if ( ! empty( $current_chunk ) ) {
210 - $texts_unknow_by_chunk[] = array(
211 - 'percentage' => 99,
212 - 'texts' => $current_chunk,
213 - );
214 - }
215 -
216 - /**
217 - * Make the reload URL
218 - */
219 -
220 - $url_reload_query_arg = array(
221 - 'wplng-load' => 'translated',
222 - 'nocache' => (string) time() . (string) rand( 100, 999 ),
223 - );
224 -
225 - if ( $args['mode'] !== 'vanilla' ) {
226 - $url_reload_query_arg['wplng-mode'] = $args['mode'];
227 - }
228 -
229 - $url_reload = add_query_arg(
230 - $url_reload_query_arg,
231 - $args['url_current']
232 - );
233 -
234 - // Ensure the reload URL is safe for JS: decode entities then use esc_url_raw (programmatic URL)
235 - $url_reload_for_js = html_entity_decode( $url_reload, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
236 - $url_reload_for_js = esc_url_raw( $url_reload_for_js );
237 -
238 - /**
239 - * JS Script - Load in progress - Data
240 - */
241 -
242 - $load_in_progress_data_js = array(
243 - 'urlAjax' => esc_url_raw( admin_url( 'admin-ajax.php' ) ),
244 - 'urlReload' => $url_reload_for_js,
245 - 'language' => esc_attr( $args['language_target'] ),
246 - 'chunks' => $texts_unknow_by_chunk,
247 - 'nonce' => wp_create_nonce( 'wplng_load_in_progress' ),
248 - );
249 -
250 - $html .= '<script id="wplingua-js-load-in-progress-data">';
251 - $html .= 'let wplngLoadInProgressData = ' . wp_json_encode( $load_in_progress_data_js ) . ';';
252 - $html .= '</script>';
253 -
254 - /**
255 - * JS Script - Load in progress - File
256 - */
257 -
258 - $script_url = plugins_url() . '/wplingua/assets/js/load-in-progress.js';
259 - $script_url .= '?ver=' . WPLNG_PLUGIN_VERSION;
260 -
261 - $html .= '<script';
262 - $html .= ' type="text/javascript"';
263 - $html .= ' src="' . esc_url( $script_url ) . '"';
264 - $html .= ' id="wplingua-js-load-in-progress-script"';
265 - $html .= '>';
266 - $html .= '</script>';
267 -
268 - /**
269 - * Place the HTML in the end of body
270 - */
271 -
272 - foreach ( $dom->find( 'body' ) as $body ) {
273 - $body->innertext = $body->innertext . $html;
274 - }
275 -
276 - return $dom;
277 -}
278 -
279 -
280 -/**
281 - * AJAX handler for "load in progress" translations.
282 - *
283 - * Validates the current user capability and incoming POST data, requests
284 - * translations for the provided texts and returns a JSON response. On error
285 - * a JSON error response is sent and execution ends.
286 - *
287 - * Expected POST parameters:
288 - * - wplng_language (string) : target language id
289 - * - wplng_texts (array) : list of texts to translate
290 - *
291 - * Permissions: current user must have 'edit_posts'.
292 - *
293 - * @return void Sends JSON success or error and exits.
294 - */
295 -function wplng_ajax_load_in_progress() {
296 -
297 - /**
298 - * Check authorizations
299 - */
300 -
301 - if ( ! current_user_can( 'edit_posts' ) ) {
302 - wp_send_json_error(
303 - array(
304 - 'error_load_in_progress' => true,
305 - 'error_message' => 'Unauthorized user',
306 - )
307 - );
308 - return;
309 - }
310 -
311 - // Verify nonce sent from client
312 - if ( empty( $_POST['wplng_nonce'] )
313 - || ! wp_verify_nonce( wp_unslash( $_POST['wplng_nonce'] ), 'wplng_load_in_progress' )
314 - ) {
315 - wp_send_json_error(
316 - array(
317 - 'error_load_in_progress' => true,
318 - 'error_message' => 'Invalid nonce',
319 - )
320 - );
321 - return;
322 - }
323 -
324 - if ( ! wplng_api_feature_is_allow( 'detection' ) ) {
325 - wp_send_json_error(
326 - array(
327 - 'error_load_in_progress' => true,
328 - 'error_message' => 'Error detecting text',
329 - )
330 - );
331 - return;
332 - }
333 -
334 - /**
335 - * Check target language
336 - */
337 -
338 - // Check if language is defined
339 -
340 - if ( empty( $_POST['wplng_language'] ) ) {
341 - wp_send_json_error(
342 - array(
343 - 'error_load_in_progress' => true,
344 - 'error_message' => 'Empty language',
345 - )
346 - );
347 - return;
348 - }
349 -
350 - $language_target = $_POST['wplng_language'];
351 -
352 - // Check if is a valid language ID
353 -
354 - if ( ! wplng_is_valid_language_id( $language_target ) ) {
355 - wp_send_json_error(
356 - array(
357 - 'error_load_in_progress' => true,
358 - 'error_message' => 'Invalid language',
359 - )
360 - );
361 - return;
362 - }
363 -
364 - // Check if languagd is allow
365 -
366 - if ( ! in_array( $language_target, wplng_get_languages_target_ids() ) ) {
367 - wp_send_json_error(
368 - array(
369 - 'error_load_in_progress' => true,
370 - 'error_message' => 'Unauthorized website language - ' . esc_attr(),
371 - )
372 - );
373 - return;
374 - }
375 -
376 - /**
377 - * Check texts to translate
378 - */
379 -
380 - if ( empty( $_POST['wplng_texts'] )
381 - || ! is_array( $_POST['wplng_texts'] )
382 - ) {
383 - wp_send_json_error(
384 - array(
385 - 'error_load_in_progress' => true,
386 - 'error_message' => 'Invalid texts data',
387 - )
388 - );
389 - return;
390 - }
391 -
392 - $texts_original_encrypted = $_POST['wplng_texts'];
393 - $texts_original = array();
394 -
395 - foreach ( $texts_original_encrypted as $text_encrypted ) {
396 - $text_decrypted = wplng_encryption_decrypt( $text_encrypted );
397 -
398 - if ( $text_decrypted === '' ) {
399 - wp_send_json_error(
400 - array(
401 - 'error_load_in_progress' => true,
402 - 'error_message' => 'Texts decryption failed',
403 - )
404 - );
405 - return;
406 - }
407 -
408 - $texts_original[] = $text_decrypted;
409 - }
410 -
411 - /**
412 - * Setup $args and get translations
413 - */
414 -
415 - $args = array( 'language_target' => $language_target );
416 - wplng_args_setup( $args );
417 - wplng_args_update_from_texts( $args, $texts_original );
418 -
419 - /**
420 - * Basic translation check
421 - */
422 -
423 - if ( empty( $args['translations'] ) ) {
424 - wp_send_json_error(
425 - array(
426 - 'error_load_in_progress' => true,
427 - 'error_message' => 'No translation returned',
428 - )
429 - );
430 - return;
431 - }
432 -
433 - /**
434 - * Setup translation array for AJAX response
435 - */
436 -
437 - $translation_response = array();
438 -
439 - foreach ( $args['translations'] as $translation ) {
440 - if ( ! isset( $translation['source'] ) || ! isset( $translation['translation'] ) ) {
441 - continue;
442 - }
443 -
444 - $translation_response[] = array(
445 - 'source' => $translation['source'],
446 - 'translation' => $translation['translation'],
447 - );
448 - }
449 -
450 - wp_send_json_success( $translation_response );
451 -}
1 +<?php
2 +
3 +// If this file is called directly, abort.
4 +if ( ! defined( 'WPINC' ) ) {
5 + die;
6 +}
7 +
8 +
9 +/**
10 + * Modify dom for the "in progress" load mode
11 + *
12 + * @param object $dom
13 + * @param array $args
14 + * @return object
15 + */
16 +function wplng_dom_load_progress( $dom, $args ) {
17 +
18 + wplng_args_setup( $args );
19 +
20 + if ( $args['load'] !== 'progress'
21 + || ! current_user_can( 'edit_posts' )
22 + ) {
23 + return $dom;
24 + }
25 +
26 + /**
27 + * Add effect on unknow texts and translate know texts
28 + */
29 +
30 + $edit_link_excluded = wplng_data_excluded_editor_link();
31 + $node_text_excluded = wplng_data_excluded_node_text();
32 +
33 + foreach ( $dom->find( 'body text' ) as $element ) {
34 +
35 + if ( in_array( $element->parent->tag, $edit_link_excluded )
36 + || in_array( $element->parent->tag, $node_text_excluded )
37 + ) {
38 + continue;
39 + }
40 +
41 + $text = $element->innertext;
42 +
43 + if ( empty( trim( $text ) ) ) {
44 + continue;
45 + }
46 +
47 + // Manage non breaking space
48 + $text = str_replace(
49 + array( '&nbsp;', html_entity_decode( '&nbsp;' ) ),
50 + array( ' ', ' ' ),
51 + $text
52 + );
53 +
54 + /**
55 + * Get spaces before and after text
56 + */
57 +
58 + $temp = array();
59 + $spaces_before = '';
60 + $spaces_after = '';
61 +
62 + preg_match( '/^(\s*).*/', $text, $temp );
63 + if ( ! empty( $temp[1] ) ) {
64 + $spaces_before = $temp[1];
65 + }
66 +
67 + preg_match( '/.*(\s*)$/U', $text, $temp );
68 + if ( ! empty( $temp[1] ) ) {
69 + $spaces_after = $temp[1];
70 + }
71 +
72 + $text = wplng_text_esc( $text );
73 + $translated = '';
74 +
75 + if ( wplng_text_is_translatable( $text ) ) {
76 +
77 + foreach ( $args['translations'] as $translation ) {
78 + if ( $text === $translation['source'] ) {
79 + $translated = $translation['translation'];
80 + break;
81 + }
82 + }
83 +
84 + if ( '' === $translated ) {
85 +
86 + $innertext = '<span';
87 + $innertext .= ' class="wplng-in-progress-text"';
88 + $innertext .= ' title="' . esc_attr__( 'Translation in progress', 'wplingua' ) . '"';
89 + $innertext .= '>';
90 + $innertext .= esc_html( $spaces_before . $text . $spaces_after );
91 + $innertext .= '</span>';
92 +
93 + $element->innertext = $innertext;
94 +
95 + } else {
96 + $element->innertext = esc_html( $spaces_before . $translated . $spaces_after );
97 + }
98 + }
99 + }
100 +
101 + /**
102 + * Create the html of message bar
103 + */
104 +
105 + $number_of_texts = (int) $args['count_texts'];
106 + $numer_of_translated_texts = count( $args['translations'] );
107 +
108 + // Calculate percentage
109 +
110 + $percentage = 0;
111 + if ( $number_of_texts > 0 ) {
112 + $percentage = (int) ( ( $numer_of_translated_texts / $number_of_texts ) * 100 );
113 + }
114 +
115 + if ( $percentage < 1 ) {
116 + $percentage = 1;
117 + }
118 +
119 + // Make the HTML
120 +
121 + $html = '<div id="wplng-in-progress-container">';
122 +
123 + $html .= '<div id="wplng-in-progress-message">';
124 + $html .= '<span class="dashicons dashicons-update wplng-spin"></span> ';
125 +
126 + $html .= '<span class="wplng-in-progress-text-mobile">';
127 + $html .= esc_html__( 'Translation in progress', 'wplingua' );
128 + $html .= '</span>';
129 +
130 + $html .= '<span class="wplng-in-progress-text-desktop">';
131 + $html .= esc_html__( 'In progress: Translation and saving of new texts', 'wplingua' );
132 + $html .= '</span>';
133 +
134 + $html .= ' - ';
135 + $html .= '<span id="wplng-in-progress-percent">';
136 + $html .= esc_html( $percentage );
137 + $html .= '</span>';
138 + $html .= ' %';
139 + $html .= '</div>'; // End #wplng-translation-in-progress
140 +
141 + $html .= '<div id="wplng-progress-bar">';
142 + $html .= '<div';
143 + $html .= ' id="wplng-progress-bar-value"';
144 + $html .= ' style="width: ' . esc_attr( $percentage ) . '%"';
145 + $html .= '>';
146 + $html .= '</div>'; // End #wplng-progress-bar-value
147 + $html .= '</div>'; // End #wplng-progress-bar
148 +
149 + $html .= '<div id="wplng-in-progress-error" style="display: none;">';
150 + $html .= '<span class="dashicons dashicons-info-outline"></span> ';
151 +
152 + $html .= '<span class="wplng-in-progress-text-mobile">';
153 + $html .= esc_html__( 'Error during translation.', 'wplingua' );
154 + $html .= '</span>';
155 +
156 + $html .= '<span class="wplng-in-progress-text-desktop">';
157 + $html .= esc_html__( 'Error during translation. Check the browser console for more information.', 'wplingua' );
158 + $html .= '</span>';
159 +
160 + $html .= '<span';
161 + $html .= ' id="wplng-in-progress-error-close"';
162 + $html .= ' class="dashicons dashicons-no-alt"';
163 + $html .= ' title="' . esc_attr__( 'Close', 'wplingua' ) . '"';
164 + $html .= '></span>';
165 +
166 + $html .= '</div>'; // End wplng-in-progress-error
167 +
168 + $html .= '</div>'; // End #wplng-in-progress-container
169 +
170 + /**
171 + * Prepare the texts chunks
172 + */
173 +
174 + $texts_unknow_by_chunk = array();
175 + $current_chunk = array();
176 + $current_chars = 0;
177 + $max_items_per_chunk = (int) ( WPLNG_MAX_TRANSLATIONS_STR / 4 );
178 + $max_chars_per_chunk = (int) ( WPLNG_MAX_TRANSLATIONS_CHAR / 4 );
179 +
180 + foreach ( $args['texts_unknow'] as $text_unknow ) {
181 +
182 + $text = (string) $text_unknow;
183 + $len = function_exists( 'mb_strlen' ) ? mb_strlen( $text, 'UTF-8' ) : strlen( $text );
184 +
185 + // If a single item is longer than allowed, truncate it to fit the limit.
186 + if ( $len > $max_chars_per_chunk ) {
187 + $text = function_exists( 'mb_substr' ) ? mb_substr( $text, 0, $max_chars_per_chunk, 'UTF-8' ) : substr( $text, 0, $max_chars_per_chunk );
188 + $len = $max_chars_per_chunk;
189 + }
190 +
191 + // If adding this text would exceed either limit, flush current chunk.
192 + if ( count( $current_chunk ) >= $max_items_per_chunk || ( $current_chars + $len ) > $max_chars_per_chunk ) {
193 + if ( ! empty( $current_chunk ) ) {
194 + $texts_unknow_by_chunk[] = array(
195 + 'percentage' => (int) ( ( $numer_of_translated_texts / $number_of_texts ) * 100 ),
196 + 'texts' => $current_chunk,
197 + );
198 + $current_chunk = array();
199 + $current_chars = 0;
200 + }
201 + }
202 +
203 + $current_chunk[] = wplng_encryption_encrypt( $text );
204 + $current_chars += $len;
205 + ++$numer_of_translated_texts;
206 +
207 + $max_items_per_chunk = (int) ( WPLNG_MAX_TRANSLATIONS_STR / 2 );
208 + $max_chars_per_chunk = (int) ( WPLNG_MAX_TRANSLATIONS_CHAR / 2 );
209 + }
210 +
211 + // Push last chunk if any
212 + if ( ! empty( $current_chunk ) ) {
213 + $texts_unknow_by_chunk[] = array(
214 + 'percentage' => 99,
215 + 'texts' => $current_chunk,
216 + );
217 + }
218 +
219 + /**
220 + * Make the reload URL
221 + */
222 +
223 + $url_reload_query_arg = array(
224 + 'wplng-load' => 'translated',
225 + 'nocache' => (string) time() . (string) rand( 100, 999 ),
226 + );
227 +
228 + if ( $args['mode'] !== 'vanilla' ) {
229 + $url_reload_query_arg['wplng-mode'] = $args['mode'];
230 + }
231 +
232 + $url_reload = add_query_arg(
233 + $url_reload_query_arg,
234 + $args['url_current']
235 + );
236 +
237 + // Ensure the reload URL is safe for JS: decode entities then use esc_url_raw (programmatic URL)
238 + $url_reload_for_js = html_entity_decode( $url_reload, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
239 + $url_reload_for_js = esc_url_raw( $url_reload_for_js );
240 +
241 + /**
242 + * JS Script - Load in progress - Data
243 + */
244 +
245 + $load_in_progress_data_js = array(
246 + 'urlAjax' => esc_url_raw( admin_url( 'admin-ajax.php' ) ),
247 + 'urlReload' => $url_reload_for_js,
248 + 'language' => esc_attr( $args['language_target'] ),
249 + 'chunks' => $texts_unknow_by_chunk,
250 + 'nonce' => wp_create_nonce( 'wplng_load_in_progress' ),
251 + );
252 +
253 + $html .= '<script id="wplingua-js-load-in-progress-data">';
254 + $html .= 'let wplngLoadInProgressData = ' . wp_json_encode( $load_in_progress_data_js ) . ';';
255 + $html .= '</script>';
256 +
257 + /**
258 + * JS Script - Load in progress - File
259 + */
260 +
261 + $script_url = plugins_url() . '/wplingua/assets/js/load-in-progress.js';
262 + $script_url .= '?ver=' . WPLNG_PLUGIN_VERSION;
263 +
264 + $html .= '<script';
265 + $html .= ' type="text/javascript"';
266 + $html .= ' src="' . esc_url( $script_url ) . '"';
267 + $html .= ' id="wplingua-js-load-in-progress-script"';
268 + $html .= '>';
269 + $html .= '</script>';
270 +
271 + /**
272 + * Place the HTML in the end of body
273 + */
274 +
275 + foreach ( $dom->find( 'body' ) as $body ) {
276 + $body->innertext = $body->innertext . $html;
277 + }
278 +
279 + return $dom;
280 +}
281 +
282 +
283 +/**
284 + * AJAX handler for "load in progress" translations.
285 + *
286 + * Validates the current user capability and incoming POST data, requests
287 + * translations for the provided texts and returns a JSON response. On error
288 + * a JSON error response is sent and execution ends.
289 + *
290 + * Expected POST parameters:
291 + * - wplng_language (string) : target language id
292 + * - wplng_texts (array) : list of texts to translate
293 + *
294 + * Permissions: current user must have 'edit_posts'.
295 + *
296 + * @return void Sends JSON success or error and exits.
297 + */
298 +function wplng_ajax_load_in_progress() {
299 +
300 + /**
301 + * Check authorizations
302 + */
303 +
304 + if ( ! current_user_can( 'edit_posts' ) ) {
305 + wp_send_json_error(
306 + array(
307 + 'error_load_in_progress' => true,
308 + 'error_message' => 'Unauthorized user',
309 + )
310 + );
311 + return;
312 + }
313 +
314 + // Verify nonce sent from client
315 + if ( empty( $_POST['wplng_nonce'] )
316 + || ! wp_verify_nonce( wp_unslash( $_POST['wplng_nonce'] ), 'wplng_load_in_progress' )
317 + ) {
318 + wp_send_json_error(
319 + array(
320 + 'error_load_in_progress' => true,
321 + 'error_message' => 'Invalid nonce',
322 + )
323 + );
324 + return;
325 + }
326 +
327 + if ( ! wplng_api_feature_is_allow( 'detection' ) ) {
328 + wp_send_json_error(
329 + array(
330 + 'error_load_in_progress' => true,
331 + 'error_message' => 'Error detecting text',
332 + )
333 + );
334 + return;
335 + }
336 +
337 + /**
338 + * Check target language
339 + */
340 +
341 + // Check if language is defined
342 +
343 + if ( empty( $_POST['wplng_language'] ) ) {
344 + wp_send_json_error(
345 + array(
346 + 'error_load_in_progress' => true,
347 + 'error_message' => 'Empty language',
348 + )
349 + );
350 + return;
351 + }
352 +
353 + $language_target = sanitize_text_field( wp_unslash( $_POST['wplng_language'] ) );
354 +
355 + // Check if is a valid language ID
356 +
357 + if ( ! wplng_is_valid_language_id( $language_target ) ) {
358 + wp_send_json_error(
359 + array(
360 + 'error_load_in_progress' => true,
361 + 'error_message' => 'Invalid language',
362 + )
363 + );
364 + return;
365 + }
366 +
367 + // Check if languagd is allow
368 +
369 + if ( ! in_array( $language_target, wplng_get_languages_target_ids() ) ) {
370 + wp_send_json_error(
371 + array(
372 + 'error_load_in_progress' => true,
373 + 'error_message' => 'Unauthorized website language - ' . esc_attr( $language_target ),
374 + )
375 + );
376 + return;
377 + }
378 +
379 + /**
380 + * Check texts to translate
381 + */
382 +
383 + if ( empty( $_POST['wplng_texts'] )
384 + || ! is_array( $_POST['wplng_texts'] )
385 + ) {
386 + wp_send_json_error(
387 + array(
388 + 'error_load_in_progress' => true,
389 + 'error_message' => 'Invalid texts data',
390 + )
391 + );
392 + return;
393 + }
394 +
395 + $texts_original_encrypted = wp_unslash( $_POST['wplng_texts'] );
396 + $texts_original = array();
397 +
398 + foreach ( $texts_original_encrypted as $text_encrypted ) {
399 + $text_decrypted = wplng_encryption_decrypt( $text_encrypted );
400 +
401 + if ( $text_decrypted === '' ) {
402 + wp_send_json_error(
403 + array(
404 + 'error_load_in_progress' => true,
405 + 'error_message' => 'Texts decryption failed',
406 + )
407 + );
408 + return;
409 + }
410 +
411 + $texts_original[] = $text_decrypted;
412 + }
413 +
414 + /**
415 + * Setup $args and get translations
416 + */
417 +
418 + $args = array( 'language_target' => $language_target );
419 + wplng_args_setup( $args );
420 + wplng_args_update_from_texts( $args, $texts_original );
421 +
422 + /**
423 + * Basic translation check
424 + */
425 +
426 + if ( empty( $args['translations'] ) ) {
427 + wp_send_json_error(
428 + array(
429 + 'error_load_in_progress' => true,
430 + 'error_message' => 'No translation returned',
431 + )
432 + );
433 + return;
434 + }
435 +
436 + /**
437 + * Setup translation array for AJAX response
438 + */
439 +
440 + $translation_response = array();
441 +
442 + foreach ( $args['translations'] as $translation ) {
443 + if ( ! isset( $translation['source'] ) || ! isset( $translation['translation'] ) ) {
444 + continue;
445 + }
446 +
447 + $translation_response[] = array(
448 + 'source' => $translation['source'],
449 + 'translation' => $translation['translation'],
450 + );
451 + }
452 +
453 + wp_send_json_success( $translation_response );
454 +}