01 · Problem
Wofür braucht man das?
UI-Texte sollen unabhängig von Komponenten organisiert, sicher umgeschaltet und mit Laufzeitwerten ergänzt werden.
02 · Denkmodell
Das mentale Modell
Ein Katalog ist Locale → Key → Template. Eine kleine zustandsbehaftete Fassade wählt das aktive Locale; Formatierung bleibt eine separate Aufgabe.
TranslationManager und Translator sind auf en/fr sowie zwei Keys fest verdrahtet, nicht exportiert und führen beim Import Demo-Logs aus. Der Paketname weicht vom üblichen i18n ab.
03 · Kontrollfluss
Was passiert in welcher Reihenfolge?
- Aktives und Fallback-Locale gegen den Katalog prüfen.
- Template erst im aktiven, dann im Fallback-Katalog suchen.
- Bekannte Platzhalter über einen festen Parser ersetzen.
- Fehlende Keys sichtbar melden statt still leere Strings zu liefern.
04 · Bauteile
Die entscheidenden Verträge
TranslationManager (intern)
Hält Katalog und aktuelles Locale.
Translator.translate (intern)
Löst einen Key auf und interpoliert Variablen.
Intl.*
Native Erweiterung für Plural-, Zahlen- und Datumsformatierung.
05 · Build it yourself
Selbst implementieren
Leite Locale- und Keytypen direkt aus einem const-Katalog ab und verwende für Platzhalter einen festen Ausdruck ohne dynamische RegExp.
- Validiere initiales und neues Locale gegen vorhandene Kataloge.
- Implementiere eine klare Fallback-Kette für fehlende Keys.
- Delegiere Zahl, Datum und Pluralisierung an Intl statt eigene Regeln zu erfinden.
function createI18n<C extends Record<string, Record<string, string>>>(
catalog: C,
initial: keyof C,
fallback: keyof C,
) {
let locale = initial;
return {
setLocale(next: keyof C) { locale = next; },
t(key: string, vars: Record<string, string> = {}) {
const text = catalog[locale][key] ?? catalog[fallback][key] ?? "[" + key + "]";
return text.replace(/\{([^}]+)\}/g, (_, name) => vars[name] ?? "{" + name + "}");
},
};
}06 · Verifizieren
Was du testen solltest
- Aktives Locale, Fallback-Locale und fehlender Key werden getrennt geprüft.
- Unbekannte und mehrfach vorkommende Platzhalter bleiben sicher und deterministisch.
- Locale-Wechsel verändert neue Übersetzungen, aber nicht bereits erzeugte Strings.
07 · Grenzen
Kompromisse und Stolperfallen
- Template-Interpolation ersetzt kein ICU-MessageFormat für komplexe Grammatik.
- Große Kataloge sollten pro Locale geladen werden, was eine Async-Schnittstelle erfordert.
Der vorhandene Code ist eine nicht exportierte Demo und sollte nicht beim Import auf die Konsole schreiben.
08 · Weiterdenken