// public/assets/js/lang.js
(function () {
const supportedLangs = ["de", "en", "it", "fr"];
let currentLang = "en";
let translations = {};
const langMeta = {
de: { flag: "🇩🇪", label: "DE" },
en: { flag: "🇬🇧", label: "EN" },
it: { flag: "🇮🇹", label: "IT" },
fr: { flag: "🇫🇷", label: "FR" }
};
// 🔹 WICHTIG:
// Diese Funktion nimmt eine verschachtelte JSON-Struktur
// und schreibt ALLE "Blatt-Keys" in ein flaches Objekt,
// OHNE den Pfad in den Keynamen einzubauen.
// D.h. { "hero": { "hero_kicker": "..." } } -> { "hero_kicker": "..." }
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 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;
const navLang = (navigator.language || navigator.userLanguage || "en")
.slice(0, 2)
.toLowerCase();
if (supportedLangs.includes(navLang)) return navLang;
return "en";
}
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); // 👈 hier wird strukturiert -> flach gemacht
} 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;
// {year}-Platzhalter ersetzen (z. B. footer_copy)
if (value.includes("{year}")) {
const year = new Date().getFullYear();
value = value.replace("{year}", year);
}
node.innerHTML = value;
});
}
function updateLangCurrentLabel(lang) {
const meta = langMeta[lang] || { flag: "", label: lang.toUpperCase() };
const node =
document.getElementById("langCurrentLabel") ||
document.getElementById("langCurrent");
if (!node) return;
if (meta.flag) {
node.innerHTML = `${meta.flag}${meta.label}`;
} else {
node.textContent = meta.label;
}
}
async function setLang(lang) {
if (!supportedLangs.includes(lang)) return;
currentLang = lang;
localStorage.setItem("usbcheck_lang", lang);
const url = new URL(window.location.href);
url.searchParams.set("lang", lang);
window.history.replaceState({}, "", url.toString());
await loadLangFile(lang);
applyTranslations();
updateLangCurrentLabel(lang);
}
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");
}
}
});
langMenu.addEventListener("click", function (e) {
const pill = e.target.closest(".lang-pill");
if (pill) {
langMenu.classList.add("hidden");
}
});
}
// Sprachumschaltung über .lang-pill
document.addEventListener("click", function (e) {
const btn = e.target.closest(".lang-pill");
if (btn) {
const lang = btn.getAttribute("data-lang");
setLang(lang);
}
});
// Login / Avatar – Dummy
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";
}
});
userAvatar.addEventListener("click", function () {
alert("Account-Menü Platzhalter – hier später Profil/Logout etc. einbauen.");
});
}
});
})();