1(function languageRedirect() { 2 function setLanguageSetting(key, value) { 3 const settings = getLanguageSetting(); 4 settings[key] = value; 5 const str = encodeURIComponent(JSON.stringify(settings)); 6 // Keep settings for a month (can revisit length later). 7 const expiration = Date.now() + 30 * 24 * 3600 * 1000; 8 window.document.cookie = `translationRedirect=${str}; expires=${expiration}; path=/; domain=smartsheet.com` 9 } 10 11 function getLanguageSetting(key) { 12 const cookieName = 'translationRedirect'; 13 const cookies = window.document.cookie.match('(^|[^;]+)\\s*' + cookieName + '\\s*=\\s*([^;]+)'); 14 const cookieValue = (cookies ? cookies.pop() : ''); 15 let settings; 16 try { 17 settings = JSON.parse(decodeURIComponent(cookieValue)); 18 } 19 catch (e) { 20 settings = {}; 21 } 22 23 if (typeof key === 'undefined') { 24 return settings; 25 } 26 return settings[key] ?? null; 27 } 28 29 function okToRedirect() { 30 // Allow people to opt out. 31 if (getLanguageSetting('optOut')) { 32 return false; 33 } 34 if (window.location.search.match(/fl_redir=opt_out/)) { 35 setLanguageSetting('optOut', 1); 36 return false; 37 } 38 39 // Avoid redirect loops. 40 if (window.location.search.match(/fl_redir=/)) { 41 return false; 42 } 43 44 // If the last redirect was within the last hour, don't do it again. 45 const lastRedirect = getLanguageSetting('lastRedirect') ?? 0; 46 const startRedirectingAgain = lastRedirect + (1000 * 60 * 60); 47 if (Date.now() < startRedirectingAgain) { 48 return false; 49 } 50 return true; 51 } 52 53 // Don't redirect anyone who has recently been redirected: 54 if (!okToRedirect()) { 55 return; 56 } 57 58 // Determine whether one of the languages we have available for this content 59 // is a better match for the user's preferences than the one we're on. 60 let available; 61 try { 62 available = new Set(JSON.parse(atob(document.documentElement.dataset.availableLanguages))); 63 } 64 catch (e) { 65 available = new Set(); 66 } 67 const userPreferences = new Set(navigator.languages.map(langcode => langcode.split('-')[0])); 68 const bestChoices = userPreferences.intersection(available); 69 70 // The <html lang=""> attribute reports the current language. 71 const currentLanguage = document.documentElement.lang ?? ''; 72 // We serve untranslated content with status code 404, and we can detect if 73 // we're on such a 404 page, because the current language won't be one of 74 // the languages Drupal reported it has available for this content. 75 const is404Message = !available.has(currentLanguage); 76 77 // If we're on a page where the user speaks the language, no redirect needed. 78 if (userPreferences.has(currentLanguage) && !is404Message) { 79 return; 80 } 81 // See if we have a translation available in one of the user's languages. 82 if (bestChoices.size > 0) { 83 const preferredLangcode = Array.from(bestChoices)[0]; 84 // Last-minute bailout: If we are redirecting to English, don't do it. 85 // English speakers don't need this functionality, and the SEO effects 86 // are not great. 87 if (preferredLangcode === 'en') { 88 return; 89 } 90 91 // Redirect to the preferred language: 92 setLanguageSetting('lastRedirect', Date.now()); 93 const param = `ss_lc=${preferredLangcode}_XX&fl_redir=1`; 94 if (window.location.search) { 95 window.location.search += `&${param}`; 96 } 97 else { 98 window.location.search = `${param}`; 99 } 100 } 101})();
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.