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

180 lines
5.5 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 translations = {};
// Mapping für Flaggen + Label im Header
const langMeta = {
de: { flag: "🇩🇪", label: "DE" },
en: { flag: "🇬🇧", label: "EN" }, // oder 🇺🇸 wenn dir lieber
it: { flag: "🇮🇹", label: "IT" },
fr: { flag: "🇫🇷", label: "FR" }
};
function flattenTranslations(obj, prefix = "") {
const result = {};
Object.keys(obj).forEach((key) => {
const value = obj[key];
const newKey = prefix ? `${prefix}_${key}` : key;
if (value && typeof value === "object" && !Array.isArray(value)) {
Object.assign(result, flattenTranslations(value, newKey));
} else {
result[newKey] = value;
}
});
return result;
}
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 data = await res.json();
translations = flattenTranslations(data);
} catch (err) {
console.error("i18n load error:", err);
translations = {};
}
}
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 || "en").slice(0, 2).toLowerCase();
if (supportedLangs.includes(navLang)) return navLang;
return "en";
}
function applyTranslations() {
document.documentElement.setAttribute("lang", getCurrentLang());
document.querySelectorAll("[data-i18n]").forEach((node) => {
const key = node.getAttribute("data-i18n");
if (!key || !translations[key]) return;
let value = translations[key];
// {year}-Placeholder ersetzen (für footer_copy etc.)
if (typeof value === "string" && value.includes("{year}")) {
const year = new Date().getFullYear();
value = value.replace("{year}", year);
}
node.innerHTML = value;
});
}
function getCurrentLang() {
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;
return "en";
}
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;
localStorage.setItem("usbcheck_lang", lang);
// URL-Parameter ohne Reload aktualisieren
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 () {
const initialLang = getInitialLang();
// Header-Label initial
updateLangCurrentLabel(initialLang);
// Übersetzungen laden und anwenden
await loadLangFile(initialLang);
applyTranslations();
// Dropdown-Elemente
const langCurrent = document.getElementById("langCurrent");
const langMenu = document.getElementById("langMenu");
// Dropdown öffnen/schließen
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 / Klick auf .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 UI-Dummy wie vorher
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.");
});
}
});
})();