PageSourceSearch

https://www.cardiff-astronomical-society.co.uk/scripts/translation.js

js cardiff-astronomical-society.co.uk collected 2026-10-08 04:47:08 UTC 4,144 bytes, 141 lines download raw bytes

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.