// public/assets/js/lang.js (function () { // --------------------------------------------- // 1) Basis-Config aus PHP (app_config.php) // --------------------------------------------- const usbConfig = window.usbConfig || {}; const i18nConfig = usbConfig.i18n || {}; // Map: { de: {code, label, flag}, en: {...}, dk: {...}, ... } const availableLangs = i18nConfig.available || {}; // Liste der unterstützten Sprachen als Codes const supportedLangs = Object.keys(availableLangs); // Sprache, die PHP in fileload.php ermittelt hat let currentLang = i18nConfig.current || usbConfig.lang || "en"; // Wenn PHP eine Sprache setzt, die nicht in available ist, nimm erste verfügbare if (!supportedLangs.includes(currentLang) && supportedLangs.length > 0) { currentLang = supportedLangs[0]; } // Fallback, wenn gar nichts da ist if (!currentLang) { currentLang = "en"; } let translations = {}; // --------------------------------------------- // 2) Helper: Translations flatten // --------------------------------------------- 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; } // --------------------------------------------- // 3) Domain-Platzhalter ersetzen // --------------------------------------------- function applyDomainPlaceholders(text) { if (typeof text !== "string") return text; const 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); } // --------------------------------------------- // 4) Initiale Sprache bestimmen // // Priorität: // a) PHP (usbConfig.i18n.current / usbConfig.lang) // b) URL ?lang= (falls gültig und in available) // c) localStorage (falls gültig) // d) erste verfügbare Sprache // --------------------------------------------- function getInitialLang() { const urlParams = new URLSearchParams(window.location.search); const paramLang = urlParams.get("lang"); if (paramLang && supportedLangs.includes(paramLang)) { return paramLang; } const stored = localStorage.getItem("usbcheck_lang"); if (stored && supportedLangs.includes(stored)) { return stored; } if (supportedLangs.includes(currentLang)) { return currentLang; } if (supportedLangs.length > 0) { return supportedLangs[0]; } return "en"; } // --------------------------------------------- // 5) i18n JSON per Fetch laden // --------------------------------------------- async function loadLangFile(lang) { try { const res = await fetch(`/assets/i18n/${lang}.json`, { cache: "no-store", }); if (!res.ok) throw new Error(`Failed to load /assets/i18n/${lang}.json`); const raw = await res.json(); translations = flattenTranslations(raw); } catch (err) { console.error("i18n load error:", err); translations = {}; } } // --------------------------------------------- // 6) Data-i18n-Texte einsetzen // --------------------------------------------- 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; // {year}-Platzhalter ersetzen (z. B. footer_copy) if (value.includes("{year}")) { const year = new Date().getFullYear(); value = value.replace("{year}", year); } value = applyDomainPlaceholders(value); node.innerHTML = value; }); } // --------------------------------------------- // 7) Label + Flag im Button aktualisieren // // Nutzt ausschließlich availableLangs aus PHP: // availableLangs[code] = { code, label, flag } // --------------------------------------------- function updateLangCurrentLabel(lang) { const info = availableLangs[lang] || { code: lang, label: lang.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; } } // --------------------------------------------- // 8) Sprache setzen // // Neu: // - akzeptiert JEDE Sprache, die in availableLangs liegt // - speichert in localStorage // - schreibt ?lang= in die URL // - lädt Seite neu, damit PHP + JS synchron sind // --------------------------------------------- async function setLang(lang) { if (!supportedLangs.includes(lang)) { console.warn("Unsupported language:", lang, supportedLangs); return; } // URL-Parameter setzen const url = new URL(window.location.href); url.searchParams.set("lang", lang); localStorage.setItem("usbcheck_lang", lang); // komplette Seite neu laden, // damit PHP (fileload.php) + Meta-Tags + JS-Konfig konsistent sind window.location.href = url.toString(); } // --------------------------------------------- // 9) DOM Ready // --------------------------------------------- document.addEventListener("DOMContentLoaded", async function () { // Initiale Sprache (kombiniert aus PHP, URL, localStorage) currentLang = getInitialLang(); updateLangCurrentLabel(currentLang); // i18n JSON laden & Texte einsetzen 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"); } } }); langMenu.addEventListener("click", function (e) { const pill = e.target.closest(".lang-pill"); if (pill) { langMenu.classList.add("hidden"); } }); } // Sprachumschaltung über .lang-pill (Buttons im Dropdown) document.addEventListener("click", function (e) { const btn = e.target.closest(".lang-pill"); if (btn) { const lang = btn.getAttribute("data-lang"); if (lang) { setLang(lang); } } }); // (Login / Avatar Dummy kann bleiben – unverändert) const loginButton = document.getElementById("loginButton"); const userAvatar = document.getElementById("userAvatar"); const avatarInitials = document.getElementById("avatarInitials"); if (loginButton && userAvatar) { loginButton.addEventListener("click", function () { loginButton.classList.add("hidden"); userAvatar.classList.remove("hidden"); if (avatarInitials && !avatarInitials.textContent.trim()) { avatarInitials.textContent = "UC"; } }); if (userAvatar) { userAvatar.addEventListener("click", function () { alert( "Account-Menü Platzhalter – hier später Profil/Logout etc. einbauen." ); }); } } }); })();