This commit is contained in:
2025-11-28 03:06:13 +01:00
parent b2be51d65e
commit 5de109b649
4 changed files with 273 additions and 363 deletions

View File

@@ -1,26 +1,14 @@
// public/assets/js/lang.js
(function () {
// ---------------------------------------------
// 1) Basis-Config aus PHP (app_config.php)
// ---------------------------------------------
const usbConfig = window.usbConfig || {};
const usbConfig = window.usbConfig || {};
const i18nConfig = usbConfig.i18n || {};
// Map: { de: {code, label, flag}, en: {...}, ... }
const availableLangs = i18nConfig.available || {};
// Liste der unterstützten Sprachen als Codes
const supportedLangs = Object.keys(availableLangs);
// Aktuelle Sprache (wird unten per getInitialLang() gesetzt)
let currentLang = "en";
// Translations-Map (geflacht)
let translations = {};
// ---------------------------------------------
// 2) Helper: Translations flatten
// ---------------------------------------------
function flattenTranslations(obj, target = {}) {
Object.keys(obj || {}).forEach((key) => {
const val = obj[key];
@@ -33,13 +21,9 @@
return target;
}
// ---------------------------------------------
// 3) Domain-Platzhalter ersetzen
// ---------------------------------------------
function applyDomainPlaceholders(text) {
if (typeof text !== "string") return text;
// Primär aus usbConfig.domains, Fallback auf window.appDomains
const domains = usbConfig.domains || window.appDomains || {};
const replacements = {
"{{primary_domain}}": domains.primaryDomain || "usbcheck.it",
@@ -58,9 +42,6 @@
}, text);
}
// ------------------------------------------------
// 4) Browsersprache erkennen (2-Buchstaben-Code)
// ------------------------------------------------
function detectBrowserLang() {
const nav = window.navigator || {};
const candidates = [];
@@ -84,58 +65,38 @@
return null;
}
// ---------------------------------------------
// 5) Initiale Sprache bestimmen
//
// Priorität:
// a) URL ?lang= (falls gültig)
// b) localStorage (explizit gewählte Sprache)
// c) Browsersprache
// d) 'en', wenn vorhanden
// e) erste verfügbare Sprache
// ---------------------------------------------
// *** Deine Priorität:
// 1) ?lang
// 2) Browser
// 3) en
function getInitialLang() {
const urlParams = new URLSearchParams(window.location.search);
const paramLang = (urlParams.get("lang") || "").toLowerCase();
// a) URL-Parameter, wenn gültig
// 1) URL-Parameter
if (paramLang && supportedLangs.includes(paramLang)) {
return paramLang;
}
// b) localStorage (vom User über Switcher gewählt)
const stored = (localStorage.getItem("usbcheck_lang") || "").toLowerCase();
if (stored) {
if (supportedLangs.includes(stored)) {
return stored;
}
// Ungültigen alten Wert aufräumen
localStorage.removeItem("usbcheck_lang");
// 2) Browsersprache
const browser = detectBrowserLang();
if (browser) {
return browser;
}
// c) Browsersprache
const browserLang = detectBrowserLang();
if (browserLang) {
return browserLang;
}
// d) Wenn 'en' existiert → nimm 'en'
// 3) EN (immer vorhanden laut deiner Vorgabe)
if (supportedLangs.includes("en")) {
return "en";
}
// e) Sonst erste verfügbare Sprache
// Sicherheitsfallback
if (supportedLangs.length > 0) {
return supportedLangs[0];
}
// Worst-Case (sollte nie eintreten)
return "en";
}
// ---------------------------------------------
// 6) i18n JSON per Fetch laden
// ---------------------------------------------
async function loadLangFile(lang) {
const code = (lang || "").toLowerCase();
if (!supportedLangs.includes(code)) {
@@ -145,9 +106,7 @@
}
try {
const res = await fetch(`/assets/i18n/${code}.json`, {
cache: "no-store",
});
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);
@@ -157,9 +116,6 @@
}
}
// ---------------------------------------------
// 7) Data-i18n-Texte einsetzen
// ---------------------------------------------
function applyTranslations() {
document.documentElement.setAttribute("lang", currentLang);
@@ -169,21 +125,16 @@
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;
});
}
// ---------------------------------------------
// 8) Label + Flag im Button aktualisieren
// ---------------------------------------------
function updateLangCurrentLabel(lang) {
const code = (lang || "").toLowerCase();
@@ -208,14 +159,8 @@
}
}
// ---------------------------------------------
// 9) Sprache setzen (via Switcher)
//
// - akzeptiert nur Sprachen aus availableLangs
// - speichert in localStorage
// - schreibt ?lang= in die URL
// - lädt Seite neu, damit PHP + JS synchron sind
// ---------------------------------------------
// 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)) {
@@ -225,20 +170,13 @@
const url = new URL(window.location.href);
url.searchParams.set("lang", code);
localStorage.setItem("usbcheck_lang", code);
window.location.href = url.toString();
}
// ---------------------------------------------
// 10) DOM Ready
// ---------------------------------------------
document.addEventListener("DOMContentLoaded", async function () {
// Initiale Sprache (kombiniert aus URL, localStorage, Browser)
currentLang = getInitialLang();
updateLangCurrentLabel(currentLang);
// i18n JSON laden & Texte einsetzen
await loadLangFile(currentLang);
applyTranslations();
@@ -258,26 +196,19 @@
}
}
});
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)
// 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) {
const lang = btn.getAttribute("data-lang");
if (lang) {
// Nur wenn data-lang gesetzt ist → JS-gesteuerter Wechsel
setLang(lang);
e.preventDefault();
}
}
if (!btn) return;
const targetLang = btn.getAttribute("data-lang");
if (!targetLang) return;
e.preventDefault();
setLang(targetLang);
});
});
})();