// public/assets/js/lang.js (function () { const usbConfig = window.usbConfig || {}; const i18nConfig = usbConfig.i18n || {}; const availableLangs = i18nConfig.available || {}; const supportedLangs = Object.keys(availableLangs); let currentLang = "en"; let translations = {}; function flattenTranslations(obj, target = {}) { Object.keys(obj || {}).forEach((key) => { const val = obj[key]; if (val && typeof val === "object" && !Array.isArray(val)) { flattenTranslations(val, target); } else { target[key] = val; } }); return target; } function applyDomainPlaceholders(text) { if (typeof text !== "string") return text; const domains = usbConfig.domains || window.appDomains || {}; const replacements = { "{{primary_domain}}": domains.primaryDomain || "usbcheck.it", "{{primary_url}}": domains.primaryUrl || "https://" + (domains.primaryDomain || "usbcheck.it"), "{{fakecheck_domain}}": domains.fakecheckDomain || "ismyusbfake.com", "{{fakecheck_url}}": domains.fakecheckUrl || "https://" + (domains.fakecheckDomain || "ismyusbfake.com"), }; return Object.keys(replacements).reduce((acc, token) => { const value = replacements[token]; return acc.split(token).join(value); }, text); } function detectBrowserLang() { const nav = window.navigator || {}; const candidates = []; if (Array.isArray(nav.languages)) { candidates.push(...nav.languages); } if (typeof nav.language === "string") { candidates.push(nav.language); } if (typeof nav.userLanguage === "string") { candidates.push(nav.userLanguage); } for (const raw of candidates) { const code = (raw || "").slice(0, 2).toLowerCase(); if (supportedLangs.includes(code)) { return code; } } return null; } // *** Deine Priorität: // 1) ?lang // 2) Browser // 3) en function getInitialLang() { const urlParams = new URLSearchParams(window.location.search); const paramLang = (urlParams.get("lang") || "").toLowerCase(); // 1) URL-Parameter if (paramLang && supportedLangs.includes(paramLang)) { return paramLang; } // 2) Browsersprache const browser = detectBrowserLang(); if (browser) { return browser; } // 3) EN (immer vorhanden laut deiner Vorgabe) if (supportedLangs.includes("en")) { return "en"; } // Sicherheitsfallback if (supportedLangs.length > 0) { return supportedLangs[0]; } return "en"; } async function loadLangFile(lang) { const code = (lang || "").toLowerCase(); if (!supportedLangs.includes(code)) { console.warn("i18n: unsupported language in loadLangFile:", code); translations = {}; return; } try { const res = await fetch(`/assets/i18n/${code}.json`, { cache: "no-store" }); if (!res.ok) throw new Error(`Failed to load /assets/i18n/${code}.json`); const raw = await res.json(); translations = flattenTranslations(raw); } catch (err) { console.error("i18n load error:", err); translations = {}; } } function applyTranslations() { document.documentElement.setAttribute("lang", currentLang); document.querySelectorAll("[data-i18n]").forEach((node) => { const key = node.getAttribute("data-i18n"); if (!key) return; let value = translations[key]; if (typeof value !== "string") return; if (value.includes("{year}")) { const year = new Date().getFullYear(); value = value.replace("{year}", year); } value = applyDomainPlaceholders(value); node.innerHTML = value; }); } function updateLangCurrentLabel(lang) { const code = (lang || "").toLowerCase(); const info = availableLangs[code] || { code: code || "en", label: (code || "en").toUpperCase(), flag: "", }; const node = document.getElementById("langCurrentLabel") || document.getElementById("langCurrent"); if (!node) return; const flag = info.flag || ""; const label = info.label || info.code.toUpperCase(); if (flag) { node.innerHTML = `${flag}${label}`; } else { node.textContent = label; } } // Wenn du später mal explizit via JS Sprache setzen willst // (z.B. beim Klick auf ein eigenes UI-Element), kannst du: function setLang(lang) { const code = (lang || "").toLowerCase(); if (!supportedLangs.includes(code)) { console.warn("Unsupported language:", code, supportedLangs); return; } const url = new URL(window.location.href); url.searchParams.set("lang", code); window.location.href = url.toString(); } document.addEventListener("DOMContentLoaded", async function () { currentLang = getInitialLang(); updateLangCurrentLabel(currentLang); await loadLangFile(currentLang); applyTranslations(); const langCurrent = document.getElementById("langCurrent"); const langMenu = document.getElementById("langMenu"); if (langCurrent && langMenu) { langCurrent.addEventListener("click", function (e) { e.stopPropagation(); langMenu.classList.toggle("hidden"); }); document.addEventListener("click", function (e) { if (!langMenu.classList.contains("hidden")) { if (!langMenu.contains(e.target) && !langCurrent.contains(e.target)) { langMenu.classList.add("hidden"); } } }); } // Nur falls du später data-lang in .lang-pill nutzt, // im aktuellen header.php kommen die Links ja direkt mit ?lang=... aus PHP. document.addEventListener("click", function (e) { const btn = e.target.closest(".lang-pill"); if (!btn) return; const targetLang = btn.getAttribute("data-lang"); if (!targetLang) return; e.preventDefault(); setLang(targetLang); }); }); })();