1$(function () { 2 // --- config 3 var rtlLangs = new Set(["ar", "fa", "ur", "he"]); 4 var defaultSrc = "auto"; // detect source automatically 5 6 // Optional: map legacy class names to language codes (fallback if data-lang-code is missing) 7 var classToCode = { 8 english: "en", 9 portuguese: "pt", 10 french: "fr", 11 german: "de", 12 spanish: "es", 13 chinese: "zh-CN", 14 japanese: "ja", 15 turkish: "tr", 16 arabic: "ar", 17 russian: "ru", 18 slovak: "sk", 19 welsh: "cy", 20 }; 21 22 // --- helpers 23 function setCookie(name, value, domain) { 24 var parts = [ 25 name + "=" + encodeURIComponent(value), 26 "path=/", 27 "max-age=" + (60 * 60 * 24 * 365).toString(), // 1 year 28 ]; 29 if (domain) parts.push("domain=" + domain); 30 document.cookie = parts.join("; "); 31 } 32 33 function getTopDomain(hostname) { 34 // Try to set cookie on the highest possible domain (e.g. .example.co.uk) 35 var parts = hostname.split("."); 36 if (parts.length <= 2) return "." + hostname; // e.g. example.com 37 // Heuristic: keep last 2 or 3 parts depending on TLD shape 38 // Safer approach: try progressively higher domains and test. We'll do that in setGoogTransCookie. 39 return null; // we'll detect dynamically 40 } 41 42 function setGoogTransCookie(lang) { 43 var val = "/" + defaultSrc + "/" + lang; 44 var host = location.hostname; 45 46 // Always set on current host 47 setCookie("googtrans", val); 48 setCookie("googtrans", val, "." + host); 49 50 // Try progressively higher domains to cover subdomains (e.g. app.site.co.uk) 51 var parts = host.split("."); 52 for (var i = 0; i < parts.length - 1; i++) { 53 var candidate = "." + parts.slice(i).join("."); 54 setCookie("googtrans", val, candidate); 55 } 56 } 57 58 function applyRtlIfNeeded(lang) { 59 if (rtlLangs.has(lang)) { 60 document.documentElement.setAttribute("dir", "rtl"); 61 document.body.classList.add("rtl"); 62 } else { 63 document.documentElement.setAttribute("dir", "ltr"); 64 document.body.classList.remove("rtl"); 65 } 66 } 67 68 function tryComboSwitch(lang) { 69 var $combo = $("#google_translate_element select.goog-te-combo"); 70 if ($combo.length) { 71 var current = $combo.val(); 72 if (current !== lang) { 73 $combo.val(lang).trigger("change"); 74 } else { 75 // Force reapply if same value 76 $combo.trigger("change"); 77 } 78 return true; 79 } 80 return false; 81 } 82 83 function switchLanguage(lang) { 84 // 1) try the combo if it's already on the page 85 if (tryComboSwitch(lang)) { 86 applyRtlIfNeeded(lang); 87 return; 88 } 89 90 // 2) otherwise set the cookie and reload so the widget picks it up 91 setGoogTransCookie(lang); 92 applyRtlIfNeeded(lang); 93 window.location.reload(); 94 } 95 96 // Observe for late-loaded translate dropdown and apply cookie-selected language without a reload loop 97 var observer = new MutationObserver(function () { 98 var cookie = document.cookie.match(/(?:^|;\s*)googtrans=([^;]+)/); 99 if (!cookie) return; 100 var val = decodeURIComponent(cookie[1]); // "/auto/<lang>" 101 var parts = val.split("/"); 102 var target = parts[2]; 103 if (target && tryComboSwitch(target)) { 104 // Once weâve successfully switched via combo, stop observing. 105 observer.disconnect(); 106 } 107 }); 108 109 observer.observe(document.documentElement || document.body, { 110 childList: true, 111 subtree: true 112 }); 113 114 // Click handler (robust, no iframe poking) 115 $(".translation-links a").off("click").on("click", function (e) { 116 e.preventDefault(); 117 118 // Prefer explicit data-lang-code 119 var lang = ($(this).data("lang-code") || "").toString().trim(); 120 121 // Fallback to class mapping if data attribute is missing 122 if (!lang) { 123 var classes = (this.className || "").split(/\s+/); 124 for (var i = 0; i < classes.length; i++) { 125 var c = classes[i].toLowerCase(); 126 if (classToCode[c]) { 127 lang = classToCode[c]; 128 break; 129 } 130 } 131 } 132 133 if (!lang) { 134 console.warn("No language code found for clicked element:", this); 135 return false; 136 } 137 138 switchLanguage(lang); 139 return false;
140 }); 141});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.