Changeset 3393354
- Timestamp:
- 11/11/2025 04:03:23 AM (5 months ago)
- Location:
- linguise
- Files:
-
- 14 edited
- 1 copied
-
tags/2.2.3 (copied) (copied from linguise/trunk)
-
tags/2.2.3/linguise.php (modified) (1 diff)
-
tags/2.2.3/readme.txt (modified) (2 diffs)
-
tags/2.2.3/src/FragmentHandler.php (modified) (10 diffs)
-
tags/2.2.3/src/constants.php (modified) (1 diff)
-
tags/2.2.3/vendor/composer/installed.php (modified) (2 diffs)
-
tags/2.2.3/vendor/linguise/script-php/certificates/cacert.pem (modified) (3 diffs)
-
tags/2.2.3/vendor/linguise/script-php/certificates/etag.txt (modified) (1 diff)
-
trunk/linguise.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/src/FragmentHandler.php (modified) (10 diffs)
-
trunk/src/constants.php (modified) (1 diff)
-
trunk/vendor/composer/installed.php (modified) (2 diffs)
-
trunk/vendor/linguise/script-php/certificates/cacert.pem (modified) (3 diffs)
-
trunk/vendor/linguise/script-php/certificates/etag.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
linguise/tags/2.2.3/linguise.php
r3388557 r3393354 5 5 * Plugin URI: https://www.linguise.com/ 6 6 * Description: Linguise translation plugin 7 * Version:2.2. 27 * Version:2.2.3 8 8 * Text Domain: linguise 9 9 * Domain Path: /languages -
linguise/tags/2.2.3/readme.txt
r3391718 r3393354 4 4 Requires at least: 4.0 5 5 Tested up to: 6.8 6 Stable tag: 2.2. 26 Stable tag: 2.2.3 7 7 Requires PHP: 7.0 8 8 License: GPLv2 or later … … 107 107 108 108 == Changelog == 109 = 2.2.3 = 110 - Fix: i18n not replaced as intended 111 109 112 = 2.2.2 = 110 113 - Fix: Unable to change language order -
linguise/tags/2.2.3/src/FragmentHandler.php
r3381590 r3393354 21 21 * @var string 22 22 */ 23 protected static $frag_html_match = '/<(div|a|linguise-main|img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip| attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?>(.*?)<\/\1>/si';23 protected static $frag_html_match = '/<(div|a|linguise-main|img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip|i18n|attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?>(.*?)<\/\1>/si'; 24 24 /** 25 25 * Regex/matcher for our custom HTML fragment … … 29 29 * @var string 30 30 */ 31 protected static $frag_html_match_self_close = '/<(img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip| attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?\s*\/?>/si';31 protected static $frag_html_match_self_close = '/<(img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip|i18n|attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?\s*\/?>/si'; 32 32 33 33 /** … … 165 165 if ($json_fragments['mode'] === 'attribute' && isset($json_fragments['attribute'])) { 166 166 $html .= ' data-fragment-extra-id="' . $json_fragments['attribute'] . '"'; 167 } 168 if ($json_fragments['mode'] === 'i18n' && isset($fragment['index'])) { 169 $html .= ' data-fragment-extra-id="' . $fragment['index'] . '"'; 167 170 } 168 171 if ($fragment['format'] === 'link') { … … 250 253 } 251 254 255 $fragment_index = null; 256 if ($fragment_mode === 'i18n' && isset($match[7]) && is_numeric($match[7])) { 257 $fragment_index = (int)$match[7]; 258 } 259 252 260 // make it into list for each fragment name 253 261 $fragments[$fragment_name][$fragment_param]['fragments'][] = [ … … 256 264 'format' => $fragment_format, 257 265 'match' => $match[0], 266 'index' => $fragment_index, 258 267 'skip' => $is_skipped, // If `skip` is true, then don't replace this fragment (but remove it) 259 268 ]; … … 346 355 347 356 /** 357 * Parse the translation block from the script tag. 358 * 359 * @param \DOMNode|\DOMElement $script The script to be matched 360 * 361 * @return array|null 362 */ 363 public static function tryMatchTranslationBlock($script) 364 { 365 $script_content = HTMLHelper::unclobberCdataInternal($script->textContent); 366 $match_res = preg_match('/\(\s*\"([\w\-_]*)\",\s*(\{.*?\})\s*\);/si', $script_content, $json_match); 367 if ($match_res === false || $match_res === 0) { 368 return null; 369 } 370 371 $block_name = $json_match[1]; 372 $json_data = json_decode($json_match[2], true); 373 if (is_null($json_data)) { 374 return null; 375 } 376 377 // WP uses Jed format for translation blocks 378 // https://messageformat.github.io/Jed/ 379 $selected_locale_data = null; 380 if (isset($json_data['locale_data'][$block_name]) && !empty($json_data['locale_data'][$block_name])) { 381 $selected_locale_data = $json_data['locale_data'][$block_name]; 382 return null; 383 } elseif (isset($json_data['locale_data']['messages']) && !empty($json_data['locale_data']['messages'])) { 384 $block_name = 'messages'; // use messages as block name 385 $selected_locale_data = $json_data['locale_data']['messages']; 386 } 387 388 if (is_null($selected_locale_data)) { 389 return null; 390 } 391 392 $collected_temp = []; 393 foreach ($selected_locale_data as $msg_key => $msg_values) { 394 if ($msg_key === '') { 395 // Skip the header 396 continue; 397 } 398 399 if (is_array($msg_values)) { 400 // for use index 401 for ($i = 0; $i < count($msg_values); $i++) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 402 // hash $msg_key in sha256 to avoid issues with quotes/special chars 403 $key_hashed = hash('sha256', $msg_key); 404 $collected_temp[] = [ 405 'key' => $key_hashed, 406 'value' => $msg_values[$i], 407 'format' => 'text', 408 'index' => $i 409 ]; 410 } 411 } 412 } 413 414 return [ 415 'name' => $block_name, 416 'fragments' => $collected_temp 417 ]; 418 } 419 420 /** 348 421 * Parse the HTML input or data into the fragments. 349 422 * XXX: Maybe normal regex and not DOMDocument if possible. … … 373 446 'fragments' => $overridden_temp['fragments'], 374 447 ]; 448 449 continue; 450 } 451 452 // Try matching -js-translations 453 $trans_match_res = preg_match('/^(.*)-js-translations$/', $attr_id, $trans_attr_match); 454 if ($trans_match_res !== false && $trans_match_res !== 0) { 455 $translation_block = self::tryMatchTranslationBlock($script); 456 $param_name = $trans_attr_match[1]; 457 if (is_array($translation_block)) { 458 $all_fragments[$param_name][$translation_block['name']] = [ 459 'mode' => 'i18n', 460 'fragments' => $translation_block['fragments'], 461 ]; 462 } 375 463 } 376 464 continue; … … 576 664 577 665 /** 666 * Apply the translated fragments for the i18n mode. 667 * 668 * @param string $html_data The HTML data to be injected 669 * @param string $param_name The name of the fragment, e.g. 'woocommerce' 670 * @param string $param_key The param of the fragment, e.g. 'messages' 671 * @param array $fragments The array of fragments to be injected, from intoJSON 672 * 673 * @return string 674 */ 675 public static function applyTranslatedFragmentsForI18n($html_data, $param_name, $param_key, $fragments) 676 { 677 $full_param_name = $param_name . '-js-translations'; 678 $overall_matchers = preg_match('/id=["\']' . preg_quote($full_param_name) . '.*?>\s*\(\s*function\(\s*domain,\s*translations\s*\)\s*\{.*?\}\s*\)\s*\(\s*["\']([\w_\-]+)["\']\s*,\s*\{(.*?)\}\s*\)\s*;\s*<\/script>/si', $html_data, $html_matches); 679 if ($overall_matchers === false || $overall_matchers === 0) { 680 return $html_data; 681 } 682 683 // Get the JSON data for replacement 684 $code_contents = $html_matches[0]; 685 $match_res = preg_match('/\(\s*\"([\w\-_]+)\",\s*(\{.*?\})\s*\);/si', $code_contents, $json_match); 686 if ($match_res === false || $match_res === 0) { 687 return $html_data; 688 } 689 690 $json_data = json_decode($json_match[2], true); 691 if (is_null($json_data)) { 692 return $html_data; 693 } 694 695 $message_data = $json_data['locale_data'][$param_key]; 696 if (empty($message_data)) { 697 return $html_data; 698 } 699 700 $remapped_fragments = []; 701 foreach ($fragments as $fragment) { 702 if (isset($fragment['skip']) && $fragment['skip']) { 703 // If skip is true, then don't replace this fragment (but remove it) 704 continue; 705 } 706 707 $msg_key = $fragment['key']; 708 $msg_index = isset($fragment['index']) ? $fragment['index'] : 0; 709 710 $remapped_fragments[$msg_key] = []; 711 $remapped_fragments[$msg_key][$msg_index] = $fragment['value']; 712 } 713 714 foreach ($message_data as $msg_key => &$msg_values) { 715 if (is_array($msg_values)) { 716 $hashed_key = hash('sha256', $msg_key); 717 if (!isset($remapped_fragments[$hashed_key])) { 718 continue; 719 } 720 721 // for use index 722 for ($i = 0; $i < count($msg_values); $i++) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 723 if (isset($remapped_fragments[$hashed_key][$i])) { 724 $msg_values[$i] = $remapped_fragments[$hashed_key][$i]; 725 } 726 } 727 } 728 } 729 730 $json_data['locale_data'][$param_key] = $message_data; 731 732 // dump back to JSON 733 $replaced_json = json_encode($json_data); 734 $substr_ptrn = '/(id=["\']' . preg_quote($full_param_name) . '["\'].*?>\s*\(\s*function\(\s*domain,\s*translations\s*\)\s*\{.*?\}\s*\)\s*\(\s*["\']([\w_\-]+)["\']\s*,\s*)(.*?)(\s*\)\s*;\s*<\/script>)/si'; 735 736 $replacement = preg_replace($substr_ptrn, '$1' . $replaced_json . '$4', $html_data, 1, $count); 737 if ($count) { 738 $html_data = $replacement; 739 } 740 741 return $html_data; 742 } 743 744 /** 578 745 * Clean up the fragments from the HTML data. 579 746 * … … 609 776 $mode = $fragment_list['mode']; 610 777 611 if (!in_array($mode, ['auto', 'override', 'skip' ])) {778 if (!in_array($mode, ['auto', 'override', 'skip', 'i18n'])) { 612 779 continue; 613 780 } … … 624 791 } 625 792 793 if ($mode === 'i18n') { 794 // i18n mode for translation blocks 795 $html_data = self::applyTranslatedFragmentsForI18n($html_data, $fragment_name, $fragment_param, $fragment_list['fragments']); 796 $html_data = self::cleanupFragments($html_data, $fragment_list['fragments']); 797 continue; 798 } 799 626 800 $id = preg_quote($fragment_name . '-js-extra', '/'); 627 801 $variable = preg_quote($fragment_param . '_params', '/'); -
linguise/tags/2.2.3/src/constants.php
r3388557 r3393354 1 1 <?php 2 2 if (!defined('LINGUISE_SCRIPT_TRANSLATION_VERSION')) { 3 define('LINGUISE_SCRIPT_TRANSLATION_VERSION', 'wordpress_plugin/2.2. 2');3 define('LINGUISE_SCRIPT_TRANSLATION_VERSION', 'wordpress_plugin/2.2.3'); 4 4 } 5 5 6 6 if (!defined('LINGUISE_VERSION')) { 7 define('LINGUISE_VERSION', '2.2. 2');7 define('LINGUISE_VERSION', '2.2.3'); 8 8 } -
linguise/tags/2.2.3/vendor/composer/installed.php
r3388557 r3393354 4 4 'pretty_version' => 'dev-master', 5 5 'version' => 'dev-master', 6 'reference' => ' d5ea0ccad80735f885e1e50abb162aa6237055ab',6 'reference' => 'f9d8386fa79f0e526a39c5c9a943cf62ca2c241a', 7 7 'type' => 'library', 8 8 'install_path' => __DIR__ . '/../../', … … 32 32 'pretty_version' => 'dev-master', 33 33 'version' => 'dev-master', 34 'reference' => ' d5ea0ccad80735f885e1e50abb162aa6237055ab',34 'reference' => 'f9d8386fa79f0e526a39c5c9a943cf62ca2c241a', 35 35 'type' => 'library', 36 36 'install_path' => __DIR__ . '/../../', -
linguise/tags/2.2.3/vendor/linguise/script-php/certificates/cacert.pem
r3358294 r3393354 2 2 ## Bundle of CA Root Certificates 3 3 ## 4 ## Certificate data from Mozilla as of: Tue Sep 9 03:12:012025 GMT4 ## Certificate data from Mozilla as of: Tue Nov 4 04:12:02 2025 GMT 5 5 ## 6 6 ## Find updated versions here: https://curl.se/docs/caextract.html … … 17 17 ## 18 18 ## Conversion done with mk-ca-bundle.pl version 1.29. 19 ## SHA256: 0 078e6bdd280fd89e1b883174387aae84b3eae2ee263416a5f8a14ee7f179ae919 ## SHA256: 039132bff5179ce57cec5803ba59fe37abe6d0297aeb538c5af27847f0702517 20 20 ## 21 21 … … 3555 3555 tnu64ZzZ 3556 3556 -----END CERTIFICATE----- 3557 3558 OISTE Server Root ECC G1 3559 ======================== 3560 -----BEGIN CERTIFICATE----- 3561 MIICNTCCAbqgAwIBAgIQI/nD1jWvjyhLH/BU6n6XnTAKBggqhkjOPQQDAzBLMQswCQYDVQQGEwJD 3562 SDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwYT0lTVEUgU2VydmVyIFJvb3Qg 3563 RUNDIEcxMB4XDTIzMDUzMTE0NDIyOFoXDTQ4MDUyNDE0NDIyN1owSzELMAkGA1UEBhMCQ0gxGTAX 3564 BgNVBAoMEE9JU1RFIEZvdW5kYXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IEVDQyBH 3565 MTB2MBAGByqGSM49AgEGBSuBBAAiA2IABBcv+hK8rBjzCvRE1nZCnrPoH7d5qVi2+GXROiFPqOuj 3566 vqQycvO2Ackr/XeFblPdreqqLiWStukhEaivtUwL85Zgmjvn6hp4LrQ95SjeHIC6XG4N2xml4z+c 3567 KrhAS93mT6NjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBQ3TYhlz/w9itWj8UnATgwQ 3568 b0K0nDAdBgNVHQ4EFgQUN02IZc/8PYrVo/FJwE4MEG9CtJwwDgYDVR0PAQH/BAQDAgGGMAoGCCqG 3569 SM49BAMDA2kAMGYCMQCpKjAd0MKfkFFRQD6VVCHNFmb3U2wIFjnQEnx/Yxvf4zgAOdktUyBFCxxg 3570 ZzFDJe0CMQCSia7pXGKDYmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c= 3571 -----END CERTIFICATE----- 3572 3573 OISTE Server Root RSA G1 3574 ========================= 3575 -----BEGIN CERTIFICATE----- 3576 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 3601 -----END CERTIFICATE----- -
linguise/tags/2.2.3/vendor/linguise/script-php/certificates/etag.txt
r3358294 r3393354 1 "3 7a4f-63e55aaf768b0"1 "3859e-642bd08b1bfbf" -
linguise/trunk/linguise.php
r3388557 r3393354 5 5 * Plugin URI: https://www.linguise.com/ 6 6 * Description: Linguise translation plugin 7 * Version:2.2. 27 * Version:2.2.3 8 8 * Text Domain: linguise 9 9 * Domain Path: /languages -
linguise/trunk/readme.txt
r3391718 r3393354 4 4 Requires at least: 4.0 5 5 Tested up to: 6.8 6 Stable tag: 2.2. 26 Stable tag: 2.2.3 7 7 Requires PHP: 7.0 8 8 License: GPLv2 or later … … 107 107 108 108 == Changelog == 109 = 2.2.3 = 110 - Fix: i18n not replaced as intended 111 109 112 = 2.2.2 = 110 113 - Fix: Unable to change language order -
linguise/trunk/src/FragmentHandler.php
r3381590 r3393354 21 21 * @var string 22 22 */ 23 protected static $frag_html_match = '/<(div|a|linguise-main|img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip| attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?>(.*?)<\/\1>/si';23 protected static $frag_html_match = '/<(div|a|linguise-main|img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip|i18n|attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?>(.*?)<\/\1>/si'; 24 24 /** 25 25 * Regex/matcher for our custom HTML fragment … … 29 29 * @var string 30 30 */ 31 protected static $frag_html_match_self_close = '/<(img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip| attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?\s*\/?>/si';31 protected static $frag_html_match_self_close = '/<(img) class="linguise-fragment" data-fragment-name="([^"]*)" data-fragment-param="([^"]*)" data-fragment-key="([^"]*)" data-fragment-format="((?:link|html|html-main|text|media-img|media-imgset)(?:-skip)?)" data-fragment-mode="(auto|override|skip|i18n|attribute)"(?: data-fragment-extra-id="([^"]*)")?(?: (?:href|src|srcset)="([^"]*)")?\s*\/?>/si'; 32 32 33 33 /** … … 165 165 if ($json_fragments['mode'] === 'attribute' && isset($json_fragments['attribute'])) { 166 166 $html .= ' data-fragment-extra-id="' . $json_fragments['attribute'] . '"'; 167 } 168 if ($json_fragments['mode'] === 'i18n' && isset($fragment['index'])) { 169 $html .= ' data-fragment-extra-id="' . $fragment['index'] . '"'; 167 170 } 168 171 if ($fragment['format'] === 'link') { … … 250 253 } 251 254 255 $fragment_index = null; 256 if ($fragment_mode === 'i18n' && isset($match[7]) && is_numeric($match[7])) { 257 $fragment_index = (int)$match[7]; 258 } 259 252 260 // make it into list for each fragment name 253 261 $fragments[$fragment_name][$fragment_param]['fragments'][] = [ … … 256 264 'format' => $fragment_format, 257 265 'match' => $match[0], 266 'index' => $fragment_index, 258 267 'skip' => $is_skipped, // If `skip` is true, then don't replace this fragment (but remove it) 259 268 ]; … … 346 355 347 356 /** 357 * Parse the translation block from the script tag. 358 * 359 * @param \DOMNode|\DOMElement $script The script to be matched 360 * 361 * @return array|null 362 */ 363 public static function tryMatchTranslationBlock($script) 364 { 365 $script_content = HTMLHelper::unclobberCdataInternal($script->textContent); 366 $match_res = preg_match('/\(\s*\"([\w\-_]*)\",\s*(\{.*?\})\s*\);/si', $script_content, $json_match); 367 if ($match_res === false || $match_res === 0) { 368 return null; 369 } 370 371 $block_name = $json_match[1]; 372 $json_data = json_decode($json_match[2], true); 373 if (is_null($json_data)) { 374 return null; 375 } 376 377 // WP uses Jed format for translation blocks 378 // https://messageformat.github.io/Jed/ 379 $selected_locale_data = null; 380 if (isset($json_data['locale_data'][$block_name]) && !empty($json_data['locale_data'][$block_name])) { 381 $selected_locale_data = $json_data['locale_data'][$block_name]; 382 return null; 383 } elseif (isset($json_data['locale_data']['messages']) && !empty($json_data['locale_data']['messages'])) { 384 $block_name = 'messages'; // use messages as block name 385 $selected_locale_data = $json_data['locale_data']['messages']; 386 } 387 388 if (is_null($selected_locale_data)) { 389 return null; 390 } 391 392 $collected_temp = []; 393 foreach ($selected_locale_data as $msg_key => $msg_values) { 394 if ($msg_key === '') { 395 // Skip the header 396 continue; 397 } 398 399 if (is_array($msg_values)) { 400 // for use index 401 for ($i = 0; $i < count($msg_values); $i++) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 402 // hash $msg_key in sha256 to avoid issues with quotes/special chars 403 $key_hashed = hash('sha256', $msg_key); 404 $collected_temp[] = [ 405 'key' => $key_hashed, 406 'value' => $msg_values[$i], 407 'format' => 'text', 408 'index' => $i 409 ]; 410 } 411 } 412 } 413 414 return [ 415 'name' => $block_name, 416 'fragments' => $collected_temp 417 ]; 418 } 419 420 /** 348 421 * Parse the HTML input or data into the fragments. 349 422 * XXX: Maybe normal regex and not DOMDocument if possible. … … 373 446 'fragments' => $overridden_temp['fragments'], 374 447 ]; 448 449 continue; 450 } 451 452 // Try matching -js-translations 453 $trans_match_res = preg_match('/^(.*)-js-translations$/', $attr_id, $trans_attr_match); 454 if ($trans_match_res !== false && $trans_match_res !== 0) { 455 $translation_block = self::tryMatchTranslationBlock($script); 456 $param_name = $trans_attr_match[1]; 457 if (is_array($translation_block)) { 458 $all_fragments[$param_name][$translation_block['name']] = [ 459 'mode' => 'i18n', 460 'fragments' => $translation_block['fragments'], 461 ]; 462 } 375 463 } 376 464 continue; … … 576 664 577 665 /** 666 * Apply the translated fragments for the i18n mode. 667 * 668 * @param string $html_data The HTML data to be injected 669 * @param string $param_name The name of the fragment, e.g. 'woocommerce' 670 * @param string $param_key The param of the fragment, e.g. 'messages' 671 * @param array $fragments The array of fragments to be injected, from intoJSON 672 * 673 * @return string 674 */ 675 public static function applyTranslatedFragmentsForI18n($html_data, $param_name, $param_key, $fragments) 676 { 677 $full_param_name = $param_name . '-js-translations'; 678 $overall_matchers = preg_match('/id=["\']' . preg_quote($full_param_name) . '.*?>\s*\(\s*function\(\s*domain,\s*translations\s*\)\s*\{.*?\}\s*\)\s*\(\s*["\']([\w_\-]+)["\']\s*,\s*\{(.*?)\}\s*\)\s*;\s*<\/script>/si', $html_data, $html_matches); 679 if ($overall_matchers === false || $overall_matchers === 0) { 680 return $html_data; 681 } 682 683 // Get the JSON data for replacement 684 $code_contents = $html_matches[0]; 685 $match_res = preg_match('/\(\s*\"([\w\-_]+)\",\s*(\{.*?\})\s*\);/si', $code_contents, $json_match); 686 if ($match_res === false || $match_res === 0) { 687 return $html_data; 688 } 689 690 $json_data = json_decode($json_match[2], true); 691 if (is_null($json_data)) { 692 return $html_data; 693 } 694 695 $message_data = $json_data['locale_data'][$param_key]; 696 if (empty($message_data)) { 697 return $html_data; 698 } 699 700 $remapped_fragments = []; 701 foreach ($fragments as $fragment) { 702 if (isset($fragment['skip']) && $fragment['skip']) { 703 // If skip is true, then don't replace this fragment (but remove it) 704 continue; 705 } 706 707 $msg_key = $fragment['key']; 708 $msg_index = isset($fragment['index']) ? $fragment['index'] : 0; 709 710 $remapped_fragments[$msg_key] = []; 711 $remapped_fragments[$msg_key][$msg_index] = $fragment['value']; 712 } 713 714 foreach ($message_data as $msg_key => &$msg_values) { 715 if (is_array($msg_values)) { 716 $hashed_key = hash('sha256', $msg_key); 717 if (!isset($remapped_fragments[$hashed_key])) { 718 continue; 719 } 720 721 // for use index 722 for ($i = 0; $i < count($msg_values); $i++) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 723 if (isset($remapped_fragments[$hashed_key][$i])) { 724 $msg_values[$i] = $remapped_fragments[$hashed_key][$i]; 725 } 726 } 727 } 728 } 729 730 $json_data['locale_data'][$param_key] = $message_data; 731 732 // dump back to JSON 733 $replaced_json = json_encode($json_data); 734 $substr_ptrn = '/(id=["\']' . preg_quote($full_param_name) . '["\'].*?>\s*\(\s*function\(\s*domain,\s*translations\s*\)\s*\{.*?\}\s*\)\s*\(\s*["\']([\w_\-]+)["\']\s*,\s*)(.*?)(\s*\)\s*;\s*<\/script>)/si'; 735 736 $replacement = preg_replace($substr_ptrn, '$1' . $replaced_json . '$4', $html_data, 1, $count); 737 if ($count) { 738 $html_data = $replacement; 739 } 740 741 return $html_data; 742 } 743 744 /** 578 745 * Clean up the fragments from the HTML data. 579 746 * … … 609 776 $mode = $fragment_list['mode']; 610 777 611 if (!in_array($mode, ['auto', 'override', 'skip' ])) {778 if (!in_array($mode, ['auto', 'override', 'skip', 'i18n'])) { 612 779 continue; 613 780 } … … 624 791 } 625 792 793 if ($mode === 'i18n') { 794 // i18n mode for translation blocks 795 $html_data = self::applyTranslatedFragmentsForI18n($html_data, $fragment_name, $fragment_param, $fragment_list['fragments']); 796 $html_data = self::cleanupFragments($html_data, $fragment_list['fragments']); 797 continue; 798 } 799 626 800 $id = preg_quote($fragment_name . '-js-extra', '/'); 627 801 $variable = preg_quote($fragment_param . '_params', '/'); -
linguise/trunk/src/constants.php
r3388557 r3393354 1 1 <?php 2 2 if (!defined('LINGUISE_SCRIPT_TRANSLATION_VERSION')) { 3 define('LINGUISE_SCRIPT_TRANSLATION_VERSION', 'wordpress_plugin/2.2. 2');3 define('LINGUISE_SCRIPT_TRANSLATION_VERSION', 'wordpress_plugin/2.2.3'); 4 4 } 5 5 6 6 if (!defined('LINGUISE_VERSION')) { 7 define('LINGUISE_VERSION', '2.2. 2');7 define('LINGUISE_VERSION', '2.2.3'); 8 8 } -
linguise/trunk/vendor/composer/installed.php
r3388557 r3393354 4 4 'pretty_version' => 'dev-master', 5 5 'version' => 'dev-master', 6 'reference' => ' d5ea0ccad80735f885e1e50abb162aa6237055ab',6 'reference' => 'f9d8386fa79f0e526a39c5c9a943cf62ca2c241a', 7 7 'type' => 'library', 8 8 'install_path' => __DIR__ . '/../../', … … 32 32 'pretty_version' => 'dev-master', 33 33 'version' => 'dev-master', 34 'reference' => ' d5ea0ccad80735f885e1e50abb162aa6237055ab',34 'reference' => 'f9d8386fa79f0e526a39c5c9a943cf62ca2c241a', 35 35 'type' => 'library', 36 36 'install_path' => __DIR__ . '/../../', -
linguise/trunk/vendor/linguise/script-php/certificates/cacert.pem
r3358294 r3393354 2 2 ## Bundle of CA Root Certificates 3 3 ## 4 ## Certificate data from Mozilla as of: Tue Sep 9 03:12:012025 GMT4 ## Certificate data from Mozilla as of: Tue Nov 4 04:12:02 2025 GMT 5 5 ## 6 6 ## Find updated versions here: https://curl.se/docs/caextract.html … … 17 17 ## 18 18 ## Conversion done with mk-ca-bundle.pl version 1.29. 19 ## SHA256: 0 078e6bdd280fd89e1b883174387aae84b3eae2ee263416a5f8a14ee7f179ae919 ## SHA256: 039132bff5179ce57cec5803ba59fe37abe6d0297aeb538c5af27847f0702517 20 20 ## 21 21 … … 3555 3555 tnu64ZzZ 3556 3556 -----END CERTIFICATE----- 3557 3558 OISTE Server Root ECC G1 3559 ======================== 3560 -----BEGIN CERTIFICATE----- 3561 MIICNTCCAbqgAwIBAgIQI/nD1jWvjyhLH/BU6n6XnTAKBggqhkjOPQQDAzBLMQswCQYDVQQGEwJD 3562 SDEZMBcGA1UECgwQT0lTVEUgRm91bmRhdGlvbjEhMB8GA1UEAwwYT0lTVEUgU2VydmVyIFJvb3Qg 3563 RUNDIEcxMB4XDTIzMDUzMTE0NDIyOFoXDTQ4MDUyNDE0NDIyN1owSzELMAkGA1UEBhMCQ0gxGTAX 3564 BgNVBAoMEE9JU1RFIEZvdW5kYXRpb24xITAfBgNVBAMMGE9JU1RFIFNlcnZlciBSb290IEVDQyBH 3565 MTB2MBAGByqGSM49AgEGBSuBBAAiA2IABBcv+hK8rBjzCvRE1nZCnrPoH7d5qVi2+GXROiFPqOuj 3566 vqQycvO2Ackr/XeFblPdreqqLiWStukhEaivtUwL85Zgmjvn6hp4LrQ95SjeHIC6XG4N2xml4z+c 3567 KrhAS93mT6NjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBQ3TYhlz/w9itWj8UnATgwQ 3568 b0K0nDAdBgNVHQ4EFgQUN02IZc/8PYrVo/FJwE4MEG9CtJwwDgYDVR0PAQH/BAQDAgGGMAoGCCqG 3569 SM49BAMDA2kAMGYCMQCpKjAd0MKfkFFRQD6VVCHNFmb3U2wIFjnQEnx/Yxvf4zgAOdktUyBFCxxg 3570 ZzFDJe0CMQCSia7pXGKDYmH5LVerVrkR3SW+ak5KGoJr3M/TvEqzPNcum9v4KGm8ay3sMaE641c= 3571 -----END CERTIFICATE----- 3572 3573 OISTE Server Root RSA G1 3574 ========================= 3575 -----BEGIN CERTIFICATE----- 3576 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 3601 -----END CERTIFICATE----- -
linguise/trunk/vendor/linguise/script-php/certificates/etag.txt
r3358294 r3393354 1 "3 7a4f-63e55aaf768b0"1 "3859e-642bd08b1bfbf"
Note: See TracChangeset
for help on using the changeset viewer.