zektyc/public/js/i18n.js

147 lines
4.6 KiB
JavaScript

(function () {
var STORAGE_KEY = "zektyc-lang"
var DEFAULT_LANG = "fr"
var translations = {}
function urlLang() {
var path = window.location.pathname
if (path === "/en" || path.indexOf("/en/") === 0) return "en"
if (path === "/fr" || path.indexOf("/fr/") === 0) return "fr"
return null
}
// Langue courante : préfixe d'URL, sinon cookie serveur (choix explicite via
// /lang), sinon localStorage, sinon détection navigateur. FR par défaut.
function pickLang() {
var forced = urlLang()
if (forced) return forced
var m = document.cookie.match(/(?:^|;\s*)zektyc-lang=([a-z]+)/)
if (m && (m[1] === "fr" || m[1] === "en")) return m[1]
try {
var stored = localStorage.getItem(STORAGE_KEY)
if (stored === "fr" || stored === "en") return stored
} catch (e) {}
var candidates = []
if (navigator.languages && navigator.languages.length) {
candidates = candidates.concat(navigator.languages)
}
if (navigator.language) candidates.push(navigator.language)
if (navigator.userLanguage) candidates.push(navigator.userLanguage)
for (var i = 0; i < candidates.length; i++) {
var raw = String(candidates[i] || "").trim().toLowerCase()
if (!raw) continue
if (raw.indexOf("en") === 0) return "en"
if (raw.indexOf("fr") === 0) return "fr"
}
return DEFAULT_LANG
}
function saveLang(lang) {
try {
localStorage.setItem(STORAGE_KEY, lang)
} catch (e) {}
document.cookie = "zektyc-lang=" + lang + "; Path=/; Max-Age=31536000"
}
function apply(lang) {
var dict = translations[lang]
if (!dict) return
document.documentElement.lang = lang
if (dict["meta.title"]) document.title = dict["meta.title"]
var desc = document.querySelector('meta[name="description"]')
if (desc && dict["meta.description"]) {
desc.setAttribute("content", dict["meta.description"])
}
var ogTitle = document.querySelector('meta[property="og:title"]')
if (ogTitle && dict["meta.title"]) {
ogTitle.setAttribute("content", dict["meta.title"])
}
var ogDesc = document.querySelector('meta[property="og:description"]')
if (ogDesc && dict["meta.description"]) {
ogDesc.setAttribute("content", dict["meta.description"])
}
var nodes = document.querySelectorAll("[data-i18n]")
for (var i = 0; i < nodes.length; i++) {
var key = nodes[i].getAttribute("data-i18n")
if (dict[key] !== undefined) nodes[i].textContent = dict[key]
}
var btns = document.querySelectorAll("[data-lang]")
for (var j = 0; j < btns.length; j++) {
btns[j].classList.toggle(
"active",
btns[j].getAttribute("data-lang") === lang
)
}
var langLinks = document.querySelectorAll("[data-lang-path]")
for (var k = 0; k < langLinks.length; k++) {
langLinks[k].setAttribute(
"href",
"/" + lang + langLinks[k].getAttribute("data-lang-path")
)
}
}
var lang = pickLang()
fetch("/data/i18n/" + lang + ".json", { cache: "no-cache" })
.then(function (res) {
if (!res.ok) throw new Error("status " + res.status)
return res.json()
})
.then(function (data) {
if (data && typeof data === "object") translations[lang] = data
})
.catch(function (e) {
if (window.console && console.warn) {
console.warn("[i18n] impossible de charger les traductions:", e)
}
})
.then(function () {
var detected = pickLang()
if (window.console && console.info) {
console.info(
"[i18n] langue détectée:",
detected,
"| navigator.language:",
navigator.language,
"| navigator.languages:",
navigator.languages
)
}
apply(detected)
document.addEventListener("click", function (e) {
var btn = e.target.closest ? e.target.closest("[data-lang]") : null
if (!btn) return
var langBtn = btn.getAttribute("data-lang")
if (langBtn !== "fr" && langBtn !== "en") return
saveLang(langBtn)
var currentPath = window.location.pathname
var target = currentPath
if (/^\/fr(\/|$)/.test(currentPath) || /^\/en(\/|$)/.test(currentPath)) {
target = "".concat("/", langBtn, currentPath.slice(3))
}
if (window.location.pathname !== target) {
window.location.href = target
}
})
var navToggle = document.getElementById("nav-toggle")
if (navToggle) {
document.addEventListener("click", function (e) {
if (e.target.closest && e.target.closest(".site-nav")) {
navToggle.checked = false
}
})
}
})
})()