Changeset 3454136
- Timestamp:
- 02/04/2026 09:24:11 PM (7 weeks ago)
- Location:
- conveythis-translate/trunk
- Files:
-
- 7 edited
-
app/class/ConveyThis.php (modified) (6 diffs)
-
app/class/Variables.php (modified) (1 diff)
-
app/views/page/widget-style.php (modified) (2 diffs)
-
app/widget/js/settings.js (modified) (11 diffs)
-
changelog.txt (modified) (1 diff)
-
index.php (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
conveythis-translate/trunk/app/class/ConveyThis.php
r3410103 r3454136 330 330 $incoming = $_POST['settings'] ?? []; 331 331 332 // These fields come as JSON strings and need to be decoded 332 333 $try_json = ['exclusions', 'glossary', 'exclusion_blocks', 'target_languages_translations']; 333 334 334 335 foreach ($try_json as $json_field) { 335 if (isset($incoming[$json_field]) && is_string($incoming[$json_field])) { 336 $incoming[$json_field] = json_decode(stripslashes($incoming[$json_field]), true); 337 } 338 } 336 if (isset($incoming[$json_field])) { 337 // Only decode if it's a string (JSON), not already an array 338 if (is_string($incoming[$json_field])) { 339 $decoded = json_decode(stripslashes($incoming[$json_field]), true); 340 if (json_last_error() === JSON_ERROR_NONE) { 341 $incoming[$json_field] = $decoded; 342 } 343 } 344 } 345 } 346 339 347 340 348 $exclusions = $incoming['exclusions'] ?? null; … … 356 364 } 357 365 366 if (!check_ajax_referer('conveythis_ajax_save', 'nonce', false)) { 367 wp_send_json_error('Invalid nonce'); 368 return; 369 } 370 358 371 foreach ($fields as $field) { 359 372 if (isset($incoming[$field])) { 360 $value = maybe_unserialize(wp_unslash($incoming[$field])); 373 $unslashed = wp_unslash($incoming[$field]); 374 375 if (is_serialized($unslashed)) { 376 if (version_compare(PHP_VERSION, '7.0.0', '>=')) { 377 $value = @unserialize($unslashed, ['allowed_classes' => false]); 378 if ($value === false && $unslashed !== serialize(false)) { 379 wp_send_json_error('Invalid data format'); 380 return; 381 } 382 } else { 383 if (preg_match('/O:\d+:"/', $unslashed)) { 384 wp_send_json_error('Invalid data format'); 385 return; 386 } 387 $value = maybe_unserialize($unslashed); 388 } 389 } else { 390 $value = $unslashed; 391 } 392 393 if ($field === 'style_change_language' || $field === 'style_change_flag') { 394 if (is_array($value)) { 395 $value = array_values($value); 396 } 397 } 398 361 399 update_option($field, $value); 362 400 } 401 } 402 403 if (!array_key_exists('style_change_language', $incoming)) { 404 update_option('style_change_language', []); 405 } 406 407 if (!array_key_exists('style_change_flag', $incoming)) { 408 update_option('style_change_flag', []); 363 409 } 364 410 … … 487 533 $this->print_log("* genIcon()"); 488 534 $i = 0; 489 while ($i < 5) { 535 while ($i < 5) { // Limit to 5 language/flag pairs 490 536 if (!empty($this->variables->style_change_language[$i]) && $this->variables->style_change_language[$i] == $language_id) { 491 537 $flag = $this->variables->style_change_flag[$i]; … … 683 729 684 730 public function updateDataPlugin() { 731 // Security: Check user capabilities before performing privileged operations 732 if (!current_user_can('manage_options')) { 733 return; 734 } 735 685 736 $this->print_log("* updateDataPlugin()"); 686 737 if (($key = array_search($this->variables->source_language, $this->variables->target_languages)) !== false) { //remove source_language from target_languages … … 732 783 733 784 function clearCacheButton() { 785 // Security: Check user capabilities before performing privileged operations 786 if (!current_user_can('manage_options')) { 787 return; 788 } 789 734 790 $this->print_log("* clearCacheButton()"); 735 791 $this->send('DELETE', '/plugin/clean-button-cache/', array( … … 1524 1580 } 1525 1581 1526 $i = 0;1527 1582 $temp = array(); 1528 1583 1529 while ($i < 5) { 1530 if (!empty($this->variables->style_change_language[$i])) { 1531 $temp[] = '"' . $this->variables->style_change_language[$i] . '":"' . $this->variables->style_change_flag[$i] . '"'; 1532 } 1533 $i++; 1584 // Ensure arrays are properly indexed and iterate through all values 1585 // Re-index arrays to ensure sequential indices (0, 1, 2, ...) 1586 $style_change_language = is_array($this->variables->style_change_language) ? array_values($this->variables->style_change_language) : array(); 1587 $style_change_flag = is_array($this->variables->style_change_flag) ? array_values($this->variables->style_change_flag) : array(); 1588 1589 // Iterate through all available pairs (up to 5) 1590 $maxPairs = min(5, max(count($style_change_language), count($style_change_flag))); 1591 1592 for ($i = 0; $i < $maxPairs; $i++) { 1593 if (!empty($style_change_language[$i])) { 1594 $langId = $style_change_language[$i]; 1595 $flagCode = !empty($style_change_flag[$i]) ? $style_change_flag[$i] : ''; 1596 $temp[] = '"' . $langId . '":"' . $flagCode . '"'; 1597 } 1534 1598 } 1535 1599 -
conveythis-translate/trunk/app/class/Variables.php
r3441289 r3454136 320 320 public $siblingsAvoidArray = ["P", "DIV", "H1", "H2", "H3", "H4", "H5", "H6", "LABEL", "LI", "SVG", "PRE"]; 321 321 322 // Flag groups for languages with multiple regional variants 323 public $chinese_traditional = [ 324 'Taiwan' => 'tw', 325 'Hong Kong' => 'hk', 326 'Macau' => 'mo' 327 ]; 328 329 public $chinese_simplified = [ 330 'Mainland China' => 'cn', 331 'Singapore' => 'sg', 332 'Malaysia' => 'my' 333 ]; 334 335 public $arabic_middle_east = [ 336 'Bahrain' => 'bh', 337 'Iraq' => 'iq', 338 'Jordan' => 'jo', 339 'Kuwait' => 'kw', 340 'Lebanon' => 'lb', 341 'Oman' => 'om', 342 'Palestine' => 'ps', 343 'Qatar' => 'qa', 344 'Saudi Arabia' => 'sa', 345 'Syria' => 'sy', 346 'United Arab Emirates' => 'ae', 347 'Yemen' => 'ye' 348 ]; 349 350 public $arabic_north_africa = [ 351 'Algeria' => 'dz', 352 'Chad' => 'td', 353 'Comoros' => 'km', 354 'Djibouti' => 'dj', 355 'Egypt' => 'eg', 356 'Eritrea' => 'er', 357 'Libya' => 'ly', 358 'Mauritania' => 'mr', 359 'Morocco' => 'ma', 360 'Somalia' => 'so', 361 'Sudan' => 'sd', 362 'Tunisia' => 'tn' 363 ]; 364 322 365 public $matchingLanguages = array( 323 703 => array('language_id' => 703, 'title_en' => 'English', 'title' => 'English', 'code2' => 'en', 'code3' => 'eng', 'flag' => 'us', 'flag_ids' => [498, 497, 342]), 324 768 => array('language_id' => 768, 'title_en' => 'Portuguese', 'title' => 'Português', 'code2' => 'pt', 'code3' => 'por', 'flag' => 'br', 'flag_ids' => [422, 318, 348]), 325 777 => array('language_id' => 777, 'title_en' => 'Spanish', 'title' => 'Español', 'code2' => 'es', 'code3' => 'spa', 'flag' => 'es', 'flag_ids' => [336]), 366 703 => array('language_id' => 703, 'title_en' => 'English', 'title' => 'English', 'code2' => 'en', 'code3' => 'eng', 'flag' => 'us', 'flag_ids' => [498, 497, 342, 320]), // US, UK, Canada, Australia 367 704 => array('language_id' => 704, 'title_en' => 'Afrikaans', 'title' => 'Afrikaans', 'code2' => 'af', 'code3' => 'afr', 'flag' => 'za', 'flag_ids' => [471, 314, 345, 349, 359, 363, 366, 408, 420, 428, 470, 476, 490]), // South Africa + North Africa 368 707 => array('language_id' => 707, 'title_en' => 'Arabic', 'title' => 'العربية', 'code2' => 'ar', 'code3' => 'ara', 'flag' => 'sa', 'flag_ids' => [324, 390, 396, 401, 405, 441, 451, 461, 481, 496, 505, 314, 345, 349, 359, 363, 366, 408, 420, 428, 470, 476, 490]), // Middle East + North Africa 369 719 => array('language_id' => 719, 'title_en' => 'Chinese (Simplified)', 'title' => '简体', 'code2' => 'zh', 'code3' => 'zho-sim', 'flag' => 'cn', 'flag_ids' => [347, 466, 415]), // Mainland China, Singapore, Malaysia 370 727 => array('language_id' => 727, 'title_en' => 'French', 'title' => 'Français', 'code2' => 'fr', 'code3' => 'fre', 'flag' => 'fr', 'flag_ids' => [371, 342]), // France, Canada 371 768 => array('language_id' => 768, 'title_en' => 'Portuguese', 'title' => 'Português', 'code2' => 'pt', 'code3' => 'por', 'flag' => 'br', 'flag_ids' => [336, 450]), // Brazil, Portugal 372 777 => array('language_id' => 777, 'title_en' => 'Spanish', 'title' => 'Español', 'code2' => 'es', 'code3' => 'spa', 'flag' => 'es', 'flag_ids' => [422, 318, 348, 474]), // Mexico, Argentina, Colombia, Spain 373 796 => array('language_id' => 796, 'title_en' => 'Chinese (Traditional)', 'title' => '繁體', 'code2' => 'zh-tw', 'code3' => 'zho-tra', 'flag' => 'cn', 'flag_ids' => [482, 508]), // Taiwan, Hong Kong, Macau 326 374 ); 327 375 328 376 public $matchingLanguageToFlag = array( 329 703 => array(498, 497, 342), 330 768 => array(336, 450), 331 777 => array(422, 318, 348, 474) 377 703 => array(498, 497, 342, 320), // US, UK, Canada, Australia 378 704 => array(471, 314, 345, 349, 359, 363, 366, 408, 420, 428, 470, 476, 490), // South Africa + North Africa 379 707 => array(324, 390, 396, 401, 405, 441, 451, 461, 481, 496, 505, 314, 345, 349, 359, 363, 366, 408, 420, 428, 470, 476, 490), // All Arabic countries 380 719 => array(347, 466, 415), // China, Singapore, Malaysia 381 727 => array(371, 342), // France, Canada 382 768 => array(336, 450), // Brazil, Portugal 383 777 => array(422, 318, 348, 474), // Mexico, Argentina, Colombia, Spain 384 796 => array(482, 508) // Taiwan, Hong Kong 332 385 ); 333 386 -
conveythis-translate/trunk/app/views/page/widget-style.php
r3410103 r3454136 71 71 <div class="col-md-6"> 72 72 <div class="ui fluid search selection dropdown change_language"> 73 <input type="hidden" name="style_change_language[]" value=""> 73 74 <i class="dropdown icon"></i> 74 75 <div class="default text"><?php echo esc_html(__( 'Select language', 'conveythis-translate' )); ?></div> … … 88 89 <div class="col-md-6"> 89 90 <div class="ui fluid search selection dropdown change_flag"> 91 <input type="hidden" name="style_change_flag[]" value=""> 90 92 <i class="dropdown icon"></i> 91 93 <div class="default text"><?php echo esc_html(__( 'Select Flag', 'conveythis-translate' )); ?></div> -
conveythis-translate/trunk/app/widget/js/settings.js
r3441289 r3454136 106 106 prepareSettingsBeforeSave(); 107 107 108 const data = Object.fromEntries(new FormData(form[0])); 109 console.log(data); 110 console.log(conveythis_plugin_ajax.ajax_url); 108 // Properly handle array inputs from FormData 109 const formData = new FormData(form[0]); 110 const data = {}; 111 112 // Fields that should be preserved as JSON strings (not parsed as arrays) 113 // CRITICAL: These fields must NEVER be converted to arrays 114 const jsonStringFields = ['glossary', 'exclusions', 'exclusion_blocks', 'target_languages_translations', 'custom_css_json']; 115 116 // Convert FormData to object, handling arrays properly 117 for (let [key, value] of formData.entries()) { 118 // SAFETY CHECK: Never process JSON string fields as arrays, even if they somehow have [] 119 if (jsonStringFields.includes(key)) { 120 // This field is a JSON string - preserve it as-is, never convert to array 121 data[key] = value; 122 continue; // Skip array processing for this field 123 } 124 125 // Handle array inputs (fields ending with []) 126 // IMPORTANT: Only process fields ending with [] as arrays 127 // JSON string fields like 'glossary' should NOT end with [] 128 if (key.endsWith('[]')) { 129 const arrayKey = key.slice(0, -2); // Remove '[]' 130 131 // EXTRA SAFETY: Double-check this isn't a JSON string field 132 if (jsonStringFields.includes(arrayKey)) { 133 console.error('[SAFETY ERROR] Attempted to process JSON field as array: ' + arrayKey); 134 // Preserve as string instead 135 data[arrayKey] = value; 136 continue; 137 } 138 139 // Only create array if key doesn't exist (prevents overwriting existing values) 140 if (!data[arrayKey]) { 141 data[arrayKey] = []; 142 } 143 // Only add non-empty values 144 if (value && value.trim() !== '') { 145 data[arrayKey].push(value); 146 } 147 } else { 148 // Regular field - preserve as-is (including JSON strings) 149 data[key] = value; 150 } 151 } 152 153 111 154 $.post(conveythis_plugin_ajax.ajax_url, { 112 155 action: 'conveythis_save_all_settings', … … 116 159 $('.conveythis-overlay').remove(); 117 160 $btn.prop('disabled', false).val('Save Settings'); 118 console.log(response)119 161 if (response.success) { 120 162 toastr.success('Settings saved successfully'); … … 278 320 'code3': 'eng', 279 321 'flag': 'R04', 280 'flag_codes': {'us': 'United States of America', 'gb': ' United Kingdom', 'ca': 'Canada' }322 'flag_codes': {'us': 'United States of America', 'gb': ' United Kingdom', 'ca': 'Canada', 'au': 'Australia'} 281 323 }, 282 704: {'title_en': 'Afrikaans', 'title': 'Afrikaans', 'code2': 'af', 'code3': 'afr', 'flag': '7xS'}, 324 704: { 325 'title_en': 'Afrikaans', 326 'title': 'Afrikaans', 327 'code2': 'af', 328 'code3': 'afr', 329 'flag': '7xS', 330 'flag_codes': { 331 'za': 'South Africa', 332 'dz': 'Algeria', 333 'td': 'Chad', 334 'km': 'Comoros', 335 'dj': 'Djibouti', 336 'eg': 'Egypt', 337 'er': 'Eritrea', 338 'ly': 'Libya', 339 'mr': 'Mauritania', 340 'ma': 'Morocco', 341 'so': 'Somalia', 342 'sd': 'Sudan', 343 'tn': 'Tunisia' 344 } 345 }, 283 346 705: {'title_en': 'Albanian', 'title': 'Shqip', 'code2': 'sq', 'code3': 'sqi', 'flag': '5iM'}, 284 347 706: {'title_en': 'Amharic', 'title': 'አማርኛ', 'code2': 'am', 'code3': 'amh', 'flag': 'ZH1'}, 285 707: {'title_en': 'Arabic', 'title': 'العربية', 'code2': 'ar', 'code3': 'ara', 'flag': 'J06'}, 348 707: { 349 'title_en': 'Arabic', 350 'title': 'العربية', 351 'code2': 'ar', 352 'code3': 'ara', 353 'flag': 'J06', 354 'flag_codes': { 355 // Middle East 356 'bh': 'Bahrain', 357 'iq': 'Iraq', 358 'jo': 'Jordan', 359 'kw': 'Kuwait', 360 'lb': 'Lebanon', 361 'om': 'Oman', 362 'ps': 'Palestine', 363 'qa': 'Qatar', 364 'sa': 'Saudi Arabia', 365 'sy': 'Syria', 366 'ae': 'United Arab Emirates', 367 'ye': 'Yemen', 368 // North Africa 369 'dz': 'Algeria', 370 'td': 'Chad', 371 'km': 'Comoros', 372 'dj': 'Djibouti', 373 'eg': 'Egypt', 374 'er': 'Eritrea', 375 'ly': 'Libya', 376 'mr': 'Mauritania', 377 'ma': 'Morocco', 378 'so': 'Somalia', 379 'sd': 'Sudan', 380 'tn': 'Tunisia' 381 } 382 }, 286 383 708: {'title_en': 'Armenian', 'title': 'Հայերեն', 'code2': 'hy', 'code3': 'hye', 'flag': 'q9U'}, 287 384 709: {'title_en': 'Azerbaijan', 'title': 'Azərbaycanca', 'code2': 'az', 'code3': 'aze', 'flag': 'Wg1'}, … … 295 392 717: {'title_en': 'Catalan', 'title': 'Català', 'code2': 'ca', 'code3': 'cat', 'flag': 'Pw6'}, 296 393 718: {'title_en': 'Cebuano', 'title': 'Cebuano', 'code2': 'ceb', 'code3': 'ceb', 'flag': ''}, 297 719: {'title_en': 'Chinese (Simplified)', 'title': '简体', 'code2': 'zh', 'code3': 'zh-sim', 'flag': 'Z1v'}, 298 796: {'title_en': 'Chinese (Traditional)', 'title': '繁體', 'code2': 'zh-tw', 'code3': 'zh-tra', 'flag': 'Z1v'}, 394 719: { 395 'title_en': 'Chinese (Simplified)', 396 'title': '简体', 397 'code2': 'zh', 398 'code3': 'zh-sim', 399 'flag': 'Z1v', 400 'flag_codes': { 401 'cn': 'Mainland China', 402 'sg': 'Singapore', 403 'my': 'Malaysia' 404 } 405 }, 406 796: { 407 'title_en': 'Chinese (Traditional)', 408 'title': '繁體', 409 'code2': 'zh-tw', 410 'code3': 'zh-tra', 411 'flag': 'Z1v', 412 'flag_codes': { 413 'tw': 'Taiwan', 414 'hk': 'Hong Kong', 415 'mo': 'Macau' 416 } 417 }, 299 418 720: {'title_en': 'Croatian', 'title': 'Hrvatski', 'code2': 'hr', 'code3': 'hrv', 'flag': '7KQ'}, 300 419 721: {'title_en': 'Czech', 'title': 'Čeština', 'code2': 'cs', 'code3': 'cze', 'flag': '1ZY'}, … … 311 430 'flag': 'nM4' 312 431 }, 313 727: {'title_en': 'French', 'title': 'Français', 'code2': 'fr', 'code3': 'fre', 'flag': 'E77'}, 432 727: { 433 'title_en': 'French', 434 'title': 'Français', 435 'code2': 'fr', 436 'code3': 'fre', 437 'flag': 'E77', 438 'flag_codes': {'fr': 'France', 'ca': 'Canada'} 439 }, 314 440 728: {'title_en': 'Galician', 'title': 'Galego', 'code2': 'gl', 'code3': 'glg', 'flag': 'A5d'}, 315 441 729: {'title_en': 'Georgian', 'title': 'ქართული', 'code2': 'ka', 'code3': 'kat', 'flag': '8Ou'}, … … 506 632 $('.conveythis-delete-page').on('click', function (e) { 507 633 //e.preventDefault(); 508 $(this).parent().remove(); 634 let $rowToDelete = $(this).closest('.style-language'); 635 if ($rowToDelete.length) { 636 // This is a flag style row - update availability after deletion 637 $rowToDelete.remove(); 638 updateLanguageDropdownAvailability(); 639 } else { 640 // Other type of row (glossary, exclusion, etc.) 641 $(this).parent().remove(); 642 } 509 643 // $(".autoSave").click(); 510 644 }); … … 555 689 e.preventDefault(); 556 690 557 if ($(".style-language").length == 4) {691 if ($(".style-language").length == 6) { // 1 cloned template + 5 actual rows = 6 total 558 692 $('#add_flag_style').prop("disable", true); 559 693 return; … … 563 697 564 698 $rule_style.removeClass('cloned') 565 $rule_style.find(' .change_language').prepend('<input type="hidden" name="style_change_language[]" value="">')566 $rule_style.find(' .change_flag').prepend('<input type="hidden" name="style_change_flag[]" value="">')699 $rule_style.find('input[name="style_change_language[]"]').val(''); 700 $rule_style.find('input[name="style_change_flag[]"]').val(''); 567 701 $("#flag-style_wrapper").append($rule_style); 568 702 569 703 $(document).find('.conveythis-delete-page').on('click', function (e) { 570 704 e.preventDefault(); 571 $(this).parent().remove(); 705 let $rowToDelete = $(this).closest('.style-language'); 706 $rowToDelete.remove(); 707 708 // Update language availability after row deletion 709 updateLanguageDropdownAvailability(); 572 710 }); 573 711 574 712 $('.ui.dropdown').dropdown(); 713 // Re-initialize handlers for all dropdowns (including the new one) 575 714 sortFlagsByLanguage(); 576 }); 577 715 // Initialize only the newly added row 716 initializeFlagDropdowns(); 717 }); 718 719 // Initialize on page load 578 720 sortFlagsByLanguage(); 721 initializeFlagDropdowns(); 579 722 580 723 $('#add_glossary').on('click', function (e) { … … 1095 1238 $('input[name="glossary"]').val(JSON.stringify(glossary)); 1096 1239 1240 // Prepare style_change_language and style_change_flag arrays 1241 // CRITICAL: Sync dropdown values to hidden inputs before collecting 1242 1243 // First, ensure all dropdown values are synced to hidden inputs 1244 $('.style-language').each(function () { 1245 let $row = $(this); 1246 let $languageDropdown = $row.find('.ui.dropdown.change_language'); 1247 let $flagDropdown = $row.find('.ui.dropdown.change_flag'); 1248 let $languageInput = $row.find('input[name="style_change_language[]"]'); 1249 let $flagInput = $row.find('input[name="style_change_flag[]"]'); 1250 1251 // Get current dropdown values 1252 let langValue = $languageDropdown.dropdown('get value'); 1253 let flagValue = $flagDropdown.dropdown('get value'); 1254 1255 // Update hidden inputs with current dropdown values 1256 if ($languageInput.length && langValue) { 1257 $languageInput.val(langValue); 1258 } 1259 if ($flagInput.length && flagValue) { 1260 $flagInput.val(flagValue); 1261 } 1262 }); 1263 1264 // Now collect from hidden inputs 1265 let style_change_language = []; 1266 let style_change_flag = []; 1267 1268 $('.style-language').each(function () { 1269 let $row = $(this); 1270 let $languageInput = $row.find('input[name="style_change_language[]"]'); 1271 let $flagInput = $row.find('input[name="style_change_flag[]"]'); 1272 1273 // Get values from hidden inputs 1274 let langValue = $languageInput.length ? $languageInput.val() : ''; 1275 let flagValue = $flagInput.length ? $flagInput.val() : ''; 1276 1277 // Only add if language is set 1278 if (langValue && langValue.trim() !== '') { 1279 style_change_language.push(langValue.trim()); 1280 style_change_flag.push(flagValue ? flagValue.trim() : ''); 1281 } 1282 }); 1283 1284 1097 1285 let exclusion_blocks = []; 1098 1286 $('div.exclusion_block').each(function () { … … 1162 1350 } 1163 1351 1352 // Function to update language dropdowns to disable already-selected languages 1353 function updateLanguageDropdownAvailability() { 1354 1355 // Get all currently selected language IDs (excluding empty values) 1356 let selectedLanguages = []; 1357 $('.style-language').each(function() { 1358 let $languageInput = $(this).find('input[name="style_change_language[]"]'); 1359 let langValue = $languageInput.length ? $languageInput.val() : ''; 1360 if (langValue && langValue.trim() !== '') { 1361 selectedLanguages.push(langValue.trim()); 1362 } 1363 }); 1364 1365 // Update all language dropdowns 1366 $('.ui.dropdown.change_language').each(function() { 1367 let $currentDropdown = $(this); 1368 let $currentRow = $currentDropdown.closest('.style-language'); 1369 let $currentInput = $currentRow.find('input[name="style_change_language[]"]'); 1370 let currentValue = $currentInput.length ? $currentInput.val() : ''; 1371 1372 // Enable/disable items in this dropdown 1373 $currentDropdown.find('.menu .item').each(function() { 1374 let $item = $(this); 1375 let itemValue = $item.attr('data-value'); 1376 1377 // If this language is selected in another row, disable it (unless it's the current row's selection) 1378 if (selectedLanguages.includes(itemValue) && itemValue !== currentValue) { 1379 $item.addClass('disabled'); 1380 } else { 1381 $item.removeClass('disabled'); 1382 } 1383 }); 1384 }); 1385 } 1386 1164 1387 // Sort flags by languages 1165 1388 function sortFlagsByLanguage() { … … 1167 1390 onChange: function (value) { 1168 1391 1392 // Update the hidden input for language 1393 let $languageInput = $(this).closest('.row').find('input[name="style_change_language[]"]'); 1394 if ($languageInput.length) { 1395 $languageInput.val(value); 1396 } 1397 1398 // Update availability of languages in all dropdowns 1399 updateLanguageDropdownAvailability(); 1400 1169 1401 let $dropdown = $(this).closest('.row').find('.ui.dropdown.change_flag'); 1170 let flagCodes = languages[value]['flag_codes']; 1171 1172 $dropdown.find('.menu').empty(); 1173 $dropdown.find('.text').empty(); 1174 1175 $.each(flagCodes, function (code, title) { 1176 1177 let newItem = $('<div class="item" data-value="' + code + '">\ 1178 <div class="ui image" style="height: 28px; width: 30px; background-position: 50% 50%;\ 1179 background-size: contain; background-repeat: no-repeat;\ 1180 background-image: url(\'//cdn.conveythis.com/images/flags/svg/' + code + '.svg\')"></div>\ 1181 ' + title + '\ 1182 </div>'); 1183 1184 $dropdown.find('.menu').append(newItem); 1185 1186 }); 1402 1403 // Check if flag_codes exists for this language 1404 if (languages[value] && languages[value]['flag_codes']) { 1405 let flagCodes = languages[value]['flag_codes']; 1406 1407 // Clear existing menu items and text 1408 $dropdown.find('.menu').empty(); 1409 $dropdown.find('.text').text('Select Flag'); 1410 $dropdown.find('input[type="hidden"]').val(''); 1411 1412 // Populate with new flag options 1413 $.each(flagCodes, function (code, title) { 1414 let newItem = $('<div class="item" data-value="' + code + '">\ 1415 <div class="ui image" style="height: 28px; width: 30px; background-position: 50% 50%;\ 1416 background-size: contain; background-repeat: no-repeat;\ 1417 background-image: url(\'//cdn.conveythis.com/images/flags/svg/' + code + '.svg\')"></div>\ 1418 ' + title + '\ 1419 </div>'); 1420 $dropdown.find('.menu').append(newItem); 1421 }); 1422 1423 // Destroy and reinitialize dropdown to ensure it recognizes new items 1424 try { 1425 $dropdown.dropdown('destroy'); 1426 } catch(e) { 1427 // Dropdown may not be initialized yet 1428 } 1429 $dropdown.dropdown(); 1430 } else { 1431 // If no flag_codes, clear the dropdown 1432 $dropdown.find('.menu').empty(); 1433 $dropdown.find('.text').text('Select Flag'); 1434 $dropdown.find('input[type="hidden"]').val(''); 1435 try { 1436 $dropdown.dropdown('destroy'); 1437 } catch(e) { 1438 // Dropdown may not be initialized yet 1439 } 1440 $dropdown.dropdown(); 1441 } 1187 1442 }, 1188 }); 1443 onRemove: function (value) { 1444 // When language is cleared/removed 1445 1446 // Clear the hidden input 1447 let $languageInput = $(this).closest('.row').find('input[name="style_change_language[]"]'); 1448 if ($languageInput.length) { 1449 $languageInput.val(''); 1450 } 1451 1452 // Update availability - re-enable this language in other dropdowns 1453 updateLanguageDropdownAvailability(); 1454 } 1455 }); 1456 1457 // Handle flag dropdown changes 1458 $('.ui.dropdown.change_flag').dropdown({ 1459 onChange: function (value) { 1460 1461 // Update the hidden input for flag 1462 let $flagInput = $(this).closest('.row').find('input[name="style_change_flag[]"]'); 1463 if ($flagInput.length) { 1464 $flagInput.val(value); 1465 } 1466 }, 1467 }); 1468 } 1469 1470 // Initialize dropdowns with saved values 1471 function initializeFlagDropdowns() { 1472 $('.style-language').each(function() { 1473 let $row = $(this); 1474 let $languageDropdown = $row.find('.ui.dropdown.change_language'); 1475 let $flagDropdown = $row.find('.ui.dropdown.change_flag'); 1476 let $languageInput = $row.find('input[name="style_change_language[]"]'); 1477 let $flagInput = $row.find('input[name="style_change_flag[]"]'); 1478 1479 // Initialize language dropdown if value exists 1480 if ($languageInput.length && $languageInput.val()) { 1481 let languageValue = $languageInput.val(); 1482 1483 // Set the language dropdown value 1484 if (languages[languageValue]) { 1485 $languageDropdown.dropdown('set selected', languageValue); 1486 1487 // Populate flags if flag_codes exists 1488 if (languages[languageValue]['flag_codes']) { 1489 let flagCodes = languages[languageValue]['flag_codes']; 1490 1491 // Clear existing menu items 1492 $flagDropdown.find('.menu').empty(); 1493 $flagDropdown.find('.text').text('Select Flag'); 1494 1495 $.each(flagCodes, function (code, title) { 1496 let newItem = $('<div class="item" data-value="' + code + '">\ 1497 <div class="ui image" style="height: 28px; width: 30px; background-position: 50% 50%;\ 1498 background-size: contain; background-repeat: no-repeat;\ 1499 background-image: url(\'//cdn.conveythis.com/images/flags/svg/' + code + '.svg\')"></div>\ 1500 ' + title + '\ 1501 </div>'); 1502 $flagDropdown.find('.menu').append(newItem); 1503 }); 1504 1505 // Destroy and reinitialize dropdown to ensure it recognizes new items 1506 try { 1507 $flagDropdown.dropdown('destroy'); 1508 } catch(e) { 1509 // Dropdown may not be initialized yet 1510 } 1511 $flagDropdown.dropdown(); 1512 1513 // Set flag value if it exists 1514 if ($flagInput.length && $flagInput.val()) { 1515 let flagValue = $flagInput.val(); 1516 $flagDropdown.dropdown('set selected', flagValue); 1517 } 1518 } 1519 } 1520 } 1521 }); 1522 1523 // Update language availability after initialization 1524 updateLanguageDropdownAvailability(); 1189 1525 } 1190 1526 -
conveythis-translate/trunk/changelog.txt
r3441289 r3454136 1 1 == Changelog == 2 = 269.2 = 3 * Added per-language flag customization and fixed a Patchstack-reported security issue. 4 2 5 = 269.1 = 3 6 * ConveyThis now supports 200+ languages -
conveythis-translate/trunk/index.php
r3441289 r3454136 4 4 Plugin URI: https://www.conveythis.com/?utm_source=widget&utm_medium=wordpress 5 5 Description: Translate your WordPress site into over 100 languages using professional and instant machine translation technology. ConveyThis will help provide you with an SEO-friendy, multilingual website in minutes with no coding required. 6 Version: 269. 16 Version: 269.2 7 7 8 8 Author: ConveyThis Translate Team -
conveythis-translate/trunk/readme.txt
r3441289 r3454136 6 6 Tested up to: 6.9 7 7 8 Stable tag: 269. 18 Stable tag: 269.2 9 9 10 10 License: GPLv2 … … 218 218 219 219 == Changelog == 220 = 269.2 = 221 * Added per-language flag customization and fixed a Patchstack-reported security issue. 222 220 223 = 269.1 = 221 224 * ConveyThis now supports 200+ languages
Note: See TracChangeset
for help on using the changeset viewer.