Files
usbcheck.it/public/assets/js/lang.js
2025-11-19 02:41:56 +01:00

169 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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 = `<span class="mr-1.5">${meta.flag}</span><span>${meta.label}</span>`;
} 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.");
});
}
});
})();