# Mehrsprachigkeit (DE/EN) – Vorschlag ## Ausgangslage Die App ist heute komplett deutschsprachig, und zwar an drei verschiedenen Stellen, die unterschiedlich behandelt werden müssen: 1. **Statisches HTML-Markup** – Labels, Überschriften, `placeholder`/`title`-Attribute direkt in `public/*.html` (`index.html`, `homing.html`, `calibration*.html`, …). Beispiel: `

Aktionen

`, ` ``` Wichtig: Der **deutsche Text bleibt im HTML stehen** (als Fallback/Default und damit die Seite ohne JS oder bei Ladefehler nicht leer ist). `i18n.js` ersetzt den Inhalt nur, wenn die Zielsprache nicht Deutsch ist bzw. wenn ein Override gesetzt wurde. Das macht die Migration risikoarm: Man kann Seite für Seite Attribute ergänzen, ohne dass etwas kaputtgeht, falls eine Seite noch nicht migriert ist. ## 3. `i18n.js` – minimale Laufzeit-Bibliothek Kernfunktionen, ca. 60–80 Zeilen, kein Tooling nötig: ```js // public/i18n.js const SUPPORTED = ['de', 'en']; const FALLBACK = 'de'; function detectLang() { const stored = localStorage.getItem('lang'); if (stored && SUPPORTED.includes(stored)) return stored; const nav = (navigator.language || FALLBACK).slice(0, 2).toLowerCase(); return SUPPORTED.includes(nav) ? nav : FALLBACK; } let dict = {}; let fallbackDict = {}; export async function initI18n() { const lang = detectLang(); [dict, fallbackDict] = await Promise.all([ fetch(`/i18n/${lang}.json`).then(r => r.json()), lang === FALLBACK ? Promise.resolve({}) : fetch(`/i18n/${FALLBACK}.json`).then(r => r.json()), ]); document.documentElement.lang = lang; applyToDom(); return lang; } export function t(key, vars) { let str = dict[key] ?? fallbackDict[key] ?? key; // Key selbst als letzter Fallback -> sichtbar im UI statt "undefined" if (vars) for (const [k, v] of Object.entries(vars)) str = str.replaceAll(`{${k}}`, v); return str; } function applyToDom(root = document) { root.querySelectorAll('[data-i18n]').forEach(el => { el.textContent = t(el.dataset.i18n); }); root.querySelectorAll('[data-i18n-attr-title]').forEach(el => { el.title = t(el.dataset.i18nAttrTitle); }); root.querySelectorAll('[data-i18n-attr-placeholder]').forEach(el => { el.placeholder = t(el.dataset.i18nAttrPlaceholder); }); } export async function setLang(lang) { localStorage.setItem('lang', lang); location.reload(); // einfach & robust, kein dynamisches Re-Rendering nötig bei dieser App-Größe } ``` Einbindung pro Seite (vor dem bestehenden Seiten-Script): ```html ``` Da `client.js`/`homing.js`/`calibration.js` aktuell keine ES-Module sind, reicht es, `initI18n()` in einem kleinen Inline-`