feat(frontend): Light-i18n + Org-Sprache durch /auth/me

Backend:
- UserMeResponse um output_language (de | en) erweitert.
- /auth/me liefert die Org-Sprache aus organization_settings.

Frontend:
- Neu: static/js/i18n.js mit T(key)-Helper, I18N.load(lang) und
  applyDom() ueber data-i18n + data-i18n-attr.
- Neu: static/i18n/de.json + en.json (sichtbare Bereiche: Sidebar,
  Header, Modal-Titel, Faktencheck-Status, Refresh-Hinweise).
- dashboard.html: i18n.js Script-Tag vor api.js, data-i18n auf den
  prominenten Strings (Abmelden, + Neuer Fall, Alle/Eigene, Sidebar-
  Sektionen, Bericht exportieren, Faktencheck-Tab, Lage anlegen).
  Tutorial.init() entfernt aus DOMContentLoaded.
- components.js: factCheckLabels/Tooltips/ChipLabels als Getter ueber
  T() mit DE-Fallbacks.
- app.js: vor Setup wird I18N.load(user.output_language) aufgerufen und
  applyDom() ausgefuehrt. Tutorial.init() laeuft nur bei lang === de.

Phase 6 von 8 (eng_demo / Org-Sprache).
Dieser Commit ist enthalten in:
Claude Code
2026-05-13 21:14:56 +00:00
Ursprung 4e51834163
Commit 3f0e680446
8 geänderte Dateien mit 271 neuen und 17 gelöschten Zeilen

Datei anzeigen

@@ -452,6 +452,14 @@ const App = {
const user = await API.getMe();
this.user = user;
this._currentUsername = user.email;
// i18n: Sprache anhand der Org laden (default 'de') und DOM uebersetzen
if (window.I18N) {
const targetLang = user.output_language || 'de';
await window.I18N.load(targetLang);
window.I18N.applyDom();
}
document.getElementById('header-user').textContent = user.email;
// Dropdown-Daten befuellen
@@ -543,6 +551,15 @@ const App = {
if (user.is_global_admin) {
this._initOrgSwitcher(user.tenant_id);
}
// Tutorial nur bei deutscher Org starten -- englische Demo-Mandanten
// sollen direkt im Dashboard landen.
try {
const lang = (window.I18N && window.I18N.lang) || 'de';
if (lang === 'de' && typeof Tutorial !== 'undefined' && Tutorial.init) {
Tutorial.init();
}
} catch (e) { /* Tutorial optional */ }
} catch {
window.location.href = '/';
return;