PluginProbe
Translation with DeepL API / trunk
Translation with DeepL API vtrunk
trunk 0.1.20180323 1.0 1.2.5.1 1.5.2.5 1.7.5 2.4.3.12 2.4.3.9 2.4.5
wpdeepl / client / deeplapi-translate.class.php

deeplapi-translate.class.php in Translation with DeepL API trunk, at client/deeplapi-translate.class.php

484 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3 class DeepLApiTranslate extends DeepLApi {
4 protected $endPoint = 'translate';
5
6 protected $langs = array( 'EN', 'DE', 'FR', 'ES', 'IT', 'NL', 'PL', 'RU' );
7 protected $syntaxes = array( 'xml', 'html' );
8
9 public $allow_cache = true;
10 protected $http_mode = 'POST';
11
12 protected $request = array(
13 'source_lang' => null,
14 'target_lang' => false,
15 'tag_handling' => 'html',
16 'ignore_tags' => 'x,code,pre',
17 'split_sentences' => 1,
18 'preserve_formatting' => 1,
19 'formality' => 'default',
20 //'glossary_id' => false,
21 'text' => array(),
22
23 );
24
25 public function getRequest() {
26 return $this->request;
27 }
28
29 protected function prepareString( $original_string, $index ) {
30 $string = $original_string;
31
32 $string = preg_replace_callback( '/\\\\u( [0-9a-fA-F]{4} )/', function ( $match ) {
33
34 $string = mb_convert_encoding( pack( 'H*', $match[1] ), 'UTF-8', 'UCS-2BE' );
35 }, $string );
36
37 $string = str_replace('&nbsp;', ' ', $string );
38 //$string = str_replace('&amp;', '&', $string );
39 $string = str_replace('&', '%26', $string );
40 //$string = str_replace( "\n", '<br class="98z4er98z4e968r4" />', $string );
41
42 if( $index == 'slug' ) {
43 $string = str_replace( '-' , ' ', $string );
44 }
45
46 // Wrap in a parent div to prevent DeepL tag_handling v2 "text without parent" error
47 // on Gutenberg content with multiple block comments.
48 $string = '<div id="wpdeepl-wrapper">' . $string . '</div>';
49
50 //$string = addslashes( $string );
51
52 return apply_filters( 'wpdeepl_' . __METHOD__, $string, $original_string );
53
54
55 $string = str_replace( '&nbsp;', ' ', $string );
56 // mandatory for POST requests
57 $string = urlencode($string);
58 //$string = htmlspecialchars($string);
59 $string = trim( $string );
60
61
62
63
64 //echo "\n ORIG $original_string \n = $string";
65
66 }
67
68 protected function splitString( $string, $length = 95000 ) {
69 $splitted_strings = array();
70
71 if( strpos( $string, '<!-- wp:') !== false ) {
72 $mode = 'blocks';
73 }
74 else {
75 $mode = 'lines';
76 }
77
78 //echo "\n mode $mode / $length / string = " . strlen( $string );
79
80 if( $mode == 'blocks' ) {
81
82 $bits = array();
83 while( strpos( $string, '<!-- /wp' ) !== false ) {
84 preg_match('#<!-- \/wp:([^>]+?)-->#ism', $string, $match );
85
86 $position = strpos( $string, $match[0] );
87 $bit = substr( $string, 0, $position + strlen( $match[0] ) );
88 $bits[] = $bit;
89 $string = substr( $string, strlen( $bit ) );
90 }
91 $bits[] = $string;
92
93
94 $current_string = '';
95 foreach( $bits as $index => $bit ) {
96 if( strlen( $current_string ) + strlen( $bit ) < $length ) {
97 $current_string .= $bit;
98 }
99 else {
100 $splitted_strings[] = $current_string;
101 $current_string = $bit;
102 }
103 }
104 $splitted_strings[] = $current_string;
105
106 }
107 else {
108 while( strlen( $string ) > $length ) {
109 $splitted_string = mb_substr( $string, 0, $length );
110 $position = mb_strrpos( $splitted_string, "\n\n" );
111 $real_split = mb_substr( $string, 0, $position );
112 $string = mb_substr( $string, $position );
113 $splitted_strings[] = $real_split;
114 }
115 $splitted_strings[] = $string;
116 }
117
118
119 foreach( $splitted_strings as $i => $string ) {
120 if ( WPDEEPL_DEBUG ) {
121 echo "\n #" . esc_html($i) . " = " . esc_html(strlen( $string ));
122 }
123 }
124 return $splitted_strings;
125 }
126
127 public function getTranslations( $strings = array(), $return_originals = false ) {
128 if ( !is_array( $strings ) ) {
129 return new WP_Error( "wrong type", "Parameter is not an array" );
130 }
131
132 $debug = true;
133 $debug = false;
134
135 $this->finalPrepareRequest();
136
137 $response = array();
138 $translated = array();
139
140 //wpdeepl_debug_display( $strings , " zeirpejzirjzi" ); //die( 'okokok' );
141
142 $extra_strings = array();
143 $extra_prepared_strings = array();
144 $prepared_strings = array();
145
146 if( $debug ) wpdeepl_debug_display( $strings);
147 if( $debug ) die('ok');
148
149
150 foreach( $strings as $string_index => $string ) {
151 $prepared_string = $this->prepareString( $string, $string_index );
152
153 if( is_array( $prepared_string ) ) {
154 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Debug logging only, no data processing.
155 wpdeepl_log( array( __METHOD__, "is array", wp_json_encode( $prepared_string ) ), 'errors' );
156 return false;
157
158 }
159 // 2.2 20230502
160 elseif( strlen( $prepared_string ) > 105000 ) {
161 $splitted_strings = $this->splitString( $string );
162 //echo "\n avant = " . strlen( $string ) ." apres =" . strlen( implode("", $splitted_strings ) );
163
164 $real_index = $string_index;
165 $string_index = false;
166
167 foreach( $splitted_strings as $i => $splitted_string ) {
168 $prepared_string = $this->prepareString( $splitted_string, $string_index );
169 if( $i == 0) {
170 $extra_strings[$real_index .':0'] = $string;
171 $prepared_strings[$real_index .':0'] = $prepared_string;
172 }
173 else {
174 $extra_strings[$real_index . ':' . $i] = $string;
175 $extra_prepared_strings[$real_index . ':' . $i] = $prepared_string;
176
177 }
178 }
179
180
181 }
182 //echo "\n $string_index = " . strlen( $string ) ." / " . strlen( $prepared_string );
183 if( $string_index )
184 $prepared_strings[$string_index] = $prepared_string;
185 }
186
187 $need_multiple_requests = false;
188 if( count( $extra_prepared_strings ) ) {
189 $need_multiple_requests = true;
190 }
191
192 $strings_requests = array();
193 $strings_requests[] = $prepared_strings;
194 if( count( $extra_prepared_strings ) ) {
195 foreach( $extra_prepared_strings as $index => $string ) {
196 $strings_requests[] = array( $index => $string );
197 }
198 }
199 $translated = array();
200
201 //wpdeepl_debug_display( $strings_requests ); wpdeepl_debug_display( $this ); die('oazeazepùiprjk');
202
203
204
205 foreach( $strings_requests as $strings_request ) {
206 $translations = $this->requestTranslation( $strings_request, $return_originals );
207 if ( is_wp_error( $translations ) ) {
208 return $translations;
209 }
210 foreach( $translations as $key => $string ) {
211 $string = str_replace('<br class="98z4er98z4e968r4" />', "\n", $string );
212 $string = str_replace('%26', '&', $string );
213 $translations[$key] = $string;
214
215 }
216 //wpdeepl_debug_display( $translations ); die('zerepzijrpjr');
217 foreach( $translations as $index => $translation ) {
218
219 $real_index = $index;
220 if (count( $strings_requests ) > 1 ) {
221 $explode = explode(':', $index );
222 if( count( $explode ) > 1 ) {
223 $real_index = $explode[0];
224 }
225 }
226 if( isset( $translated[$real_index] ) ) {
227 $translated[$real_index] .= $translation;
228 }
229 else {
230 $translated[$real_index] = $translation;
231 }
232 }
233 }
234 if( isset( $translated['slug'] ) ) {
235 $translated['slug'] = str_replace( ' ', '-', $translated['slug'] );
236 }
237
238 //wpdeepl_debug_display( $this);
239 //wpdeepl_debug_display( $strings_requests , "strings reuqests"); wpdeepl_debug_display( $translated, " TRANSLATED" ); die('az54eaze684eaok');
240
241 return $translated;
242 }
243
244 protected function requestTranslation( $strings, $return_originals ) {
245 $this->resetTexts();
246 $translated = array();
247
248 //$this->allow_cache = false;
249
250 $string_indexes = array();
251 $i = 0;
252 $cache_id_strings = '';
253 //wpdeepl_debug_display( $strings) ;
254 foreach ( $strings as $string_index => $string ) {
255 if( empty( trim( $string ) ) ) {
256 unset( $strings[$string_index] );
257 }
258 }
259 foreach ( $strings as $string_index => $string ) {
260
261 $string_indexes[$i] = $string_index;
262 $i++;
263 $cache_id_strings .= $string;
264 $this->addText( $string );
265 if ( $return_originals ) {
266 $translated['_original_' . $string_index] = urldecode($string);
267 }
268 }
269
270 $cache_id = ( $this->request['source_lang'] ) ? $this->request['source_lang'] : 'AUTO';
271 $cache_id .= ':' . $this->request['target_lang'] . ':' . md5( $cache_id_strings );
272 $this->setCacheID( $cache_id );
273 // wpdeepl_debug_display( $strings, "strings donc cache id $cache_id");
274
275 //wpdeepl_debug_display($this); die('okaziejaiej');
276 if ( !$this->isValidRequest() ) {
277 $return = new WP_Error( "bad request", "Bof" );
278 return $return;
279 }
280
281 // wpdeepl_debug_display( $this ); die('rzeokroezrk');
282
283
284 $response = $this->request();
285
286 if ( is_wp_error( $response ) ) {
287 return $response;
288 }
289 if ( !array_key_exists( 'translations', $response ) ) {
290 $return = new WP_Error( "bad response", $response );
291 }
292
293 foreach ( $response['translations'] as $index => $translation ) {
294 $string_index = $string_indexes[$index];
295 $translated_text = $translation->text;
296
297 // 2021 04 14
298 $translated_text = str_replace( '&lt;!--', '<!--', $translated_text );
299 $translated_text = str_replace( '--&gt;', '-->', $translated_text );
300 $translated_text = str_replace( '--&gt', '-->', $translated_text );
301
302 $translated_text = str_replace( '-->', "-->\n", $translated_text );
303
304 // Strip the wrapper div added in prepareString()
305 $translated_text = preg_replace( '#^<div id="wpdeepl-wrapper">(.*)</div>$#s', '$1', $translated_text );
306
307 $translated[$string_index] = $translated_text;
308 }
309
310 //wpdeepl_debug_display( $response, "response" ); wpdeepl_debug_display( $string_indexes, "indexes"); wpdeepl_debug_display( $translated, "transalted");
311 // die('okokeroz');
312 //wpdeepl_debug_display( $translated, "translated");die('oizeeizjrirj');
313 return $translated;
314 }
315
316 public function buildBody( $mode = 'POST', $endPoint = '' ) {
317 $endPoint = $this->endPoint;
318 $body = array();
319
320 //if ( count( $this->headers ) ) $args['headers'] = $this->headers;
321
322 //$request = array( 'auth_key' => $this->authKey );
323
324 // wpdeepl_debug_display( $this->request); die(('ozeozrkzr'));
325
326
327 foreach( array( 'target_lang', 'source_lang', 'tag_handling', 'ignore_tags','split_sentences', 'preserve_formatting', 'formality' ) as $tag ) {
328 if( !empty( $this->request[$tag] ) ) {
329 $body[] = "$tag=" . $this->request[$tag];
330 }
331 }
332 $glossary_id = DeepLConfiguration::getActiveGlossaryFor( $this->request['source_lang'], $this->request['target_lang'] );
333 if( $glossary_id )
334 $body[] = "glossary_id=$glossary_id";
335
336 if ( $mode == 'POST' ) {
337 // fixed in 0.3 by schalipp https://wordpress.org/support/topic/translate-button-not-doing-anything/#post-10825822
338 // modified in 1.0 to send all strings in one request
339
340 foreach( $this->request['text'] as $string ) {
341 if( !empty( $string ) )
342 $body[] = "text=" . ( $string );
343 }
344
345 }
346 else {
347 }
348
349 $body = implode( '&', $body );
350 $this->final_request['body'] = $body;
351 //wpdeepl_debug_display($this);die('ezorozrk');
352 $this->saveRequest();
353 return $body;
354 }
355
356 /*
357 public function resetQuery() {
358 $this->request = array();
359 $this->headers = array();
360 }*/
361
362 private function finalPrepareRequest() {
363
364 /*
365 Sets whether the translated text should lean towards formal or informal language. This feature currently only works for target languages "DE" (German), "FR" (French), "IT" (Italian), "ES" (Spanish), "NL" (Dutch), "PL" (Polish), "PT-PT", "PT-BR" (Portuguese) and "RU" (Russian).
366 */
367
368 /*
369 no need to unset, just keep it useless
370 $target_lang = $this->request['target_lang'];
371 if ( !in_array( $target_lang, array('DE', 'FR', 'IT', 'ES', 'NL', 'PL', 'PT-PT', 'PT-BR', 'RU' ) ) ) {
372 unset( $this->request['formality'] );
373 }
374 */
375
376 return;
377 }
378
379 public function addText( $string ) {
380 $this->request['text'][] = $string;
381 return strlen( implode( '', $this->request['text'] ) );
382 }
383
384 protected function resetTexts() {
385 $this->request['text'] = array();
386 }
387
388 public function setLangFrom( $source_lang = false ) {
389 if ( !$source_lang ) {
390 return true;
391 }
392
393 $source = DeeplConfiguration::validateLang( $source_lang, 'assource' );
394 if ( $source ) {
395 $this->request['source_lang'] = $source;
396 return true;
397 }
398 else {
399 return true;
400 }
401 }
402
403 public function setLangTo( $target_lang ) {
404 if ( !$target_lang ) {
405 return false;
406 }
407
408 $target = DeeplConfiguration::validateLang( $target_lang, 'astarget' );
409 if ( !$target ) {
410 return false;
411 }
412 else {
413 $this->request['target_lang'] = $target;
414 return true;
415 }
416 }
417
418 public function setTagHandling( $tag_handling = 'html' ) {
419 if ( $tag_handling && in_array( $tag_handling, $this->syntaxes ) ) {
420 $this->request['tag_handling'] = $tag_handling;
421 return true;
422 }
423 }
424
425 public function setSplitSentences( $split_sentences = true ) {
426 if ( false === filter_var( $split_sentences, FILTER_VALIDATE_BOOLEAN ) ) {
427 $this->request['split_sentences'] = 0;
428 }
429 else {
430 $this->request['split_sentences'] = 1;
431 }
432 }
433
434 public function setFormality( $formality = 'default' ) {
435 if ( in_array( $formality, array('more', 'less', 'prefer_more', 'prefer_less', 'default' ) ) ) {
436 $this->request['formality'] = $formality;
437 }
438 else {
439 }
440 }
441
442 public function setGlossary( $glossary_id ) {
443
444 if( $glossary_id )
445 $this->request['glossary_id'] = $glossary_id;
446 }
447
448 public function setPreserveFormatting( $preserve_formatting = false ) {
449 if ( true === filter_var( $split_sentences, FILTER_VALIDATE_BOOLEAN ) ) {
450 $this->request['preserve_formatting'] = 1;
451 }
452 else {
453 $this->request['preserve_formatting'] = 0;
454 }
455 }
456
457 public function getRequestUniqueID() {
458 $this->uniqid = md5( implode( '',$this->request['text'] ) );
459 return $this->uniqid;
460 }
461
462 // RESPONSE
463 public function getDetectedLanguage() {
464 if ( !isset( $this->result ) || !array_key_exists( 'detected_source_language', $this->result ) ) {
465 return false;
466 }
467 return $this->result['detected_source_language'];
468 }
469
470 public function getMessage() {
471 if ( !isset( $this->result ) || !array_key_exists( 'message', $this->result ) ) {
472 return false;
473 }
474 return $this->result['message'];
475 }
476 public function getTranslatedText() {
477 if ( !isset( $this->result ) || !array_key_exists( 'text', $this->result ) ) {
478 return false;
479 }
480 return $this->result['text'];
481 }
482 }
483
484