1(function () { 2 'use strict'; 3 4 var STORAGE_KEY = 'ted_gt_lang'; 5 var isTranslating = false; 6 var debounceTimer = null; 7 8 // Required callback name for the GT SDK script tag 9 window.googleTranslateElementInit = function () { 10 new google.translate.TranslateElement({ 11 pageLanguage: 'en', 12 includedLanguages: '', 13 autoDisplay: false 14 }, 'google_translate_element'); 15 16 // Ensure English is available in the combo as a target 17 setTimeout(function () { 18 var select = document.querySelector('.goog-te-combo'); 19 if (select && !select.querySelector('option[value="en"]')) { 20 var opt = document.createElement('option'); 21 opt.value = 'en'; 22 opt.text = 'English'; 23 select.insertBefore(opt, select.firstChild); 24 } 25 restoreLanguage(); 26 }, 1500); 27 }; 28 29 function restoreLanguage() { 30 var lang = localStorage.getItem(STORAGE_KEY); 31 if (lang && lang !== 'en') { 32 applyLanguage(lang); 33 } 34 } 35 36 function applyLanguage(langCode) { 37 var select = document.querySelector('.goog-te-combo'); 38 if (!select) return; 39 40 isTranslating = true; 41 select.value = langCode; 42 select.dispatchEvent(new Event('change')); 43 setTimeout(function () { isTranslating = false; }, 1500); 44 } 45 46 window.tedSetGoogleTranslateLanguage = function (langCode) { 47 localStorage.setItem(STORAGE_KEY, langCode); 48 applyLanguage(langCode); 49 }; 50 51 // Check if a node is UI chrome that should not trigger re-translation 52 // (popovers, overlays, menus, tooltips, etc.) 53 function isUIChrome(node) { 54 if (node.nodeType !== Node.ELEMENT_NODE) return false; 55 var cl = node.classList; 56 if (!cl) return false; 57 return cl.contains('mud-popover') 58 || cl.contains('mud-overlay') 59 || cl.contains('mud-menu') 60 || cl.contains('mud-list') 61 || cl.contains('mud-tooltip') 62 || cl.contains('mud-picker') 63 || cl.contains('mud-dialog') 64 || cl.contains('notranslate') 65 || cl.contains('skiptranslate') 66 || node.tagName === 'FONT'; 67 } 68 69 // Walk up the DOM to check if a node is inside UI chrome 70 function isInsideUIChrome(node) { 71 var el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement; 72 while (el && el !== document.body) { 73 if (isUIChrome(el)) return true; 74 el = el.parentElement; 75 } 76 return false; 77 } 78 79 // Re-apply translation after Blazor DOM updates 80 // Only triggers for actual page content changes, not popover/menu/overlay activity 81 var observer = new MutationObserver(function (mutations) { 82 if (isTranslating) return; 83 var lang = localStorage.getItem(STORAGE_KEY); 84 if (!lang || lang === 'en') return; 85 86 var hasNewContent = mutations.some(function (m) { 87 return Array.from(m.addedNodes).some(function (n) { 88 return n.nodeType === Node.ELEMENT_NODE 89 && !isUIChrome(n) 90 && !isInsideUIChrome(n); 91 }); 92 }); 93 94 if (!hasNewContent) return; 95 96 clearTimeout(debounceTimer); 97 debounceTimer = setTimeout(function () { 98 applyLanguage(lang); 99 }, 500); 100 }); 101 102 document.addEventListener('DOMContentLoaded', function () { 103 observer.observe(document.body, { childList: true, subtree: true }); 104 }); 105 106}());
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.