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.
Löst Sprachkataloge auf und ersetzt Platzhalter durch literale Werte. Eine Pluralnachrichtensyntax ist nicht implementiert. Für Datum, Zahlen und Pluralauswahl eignet sich Intl.
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
TranslationManagerWählt eine unterstützte Katalogsprache.Translator.translate(key, variables?)Löst einen Schlüssel auf und ersetzt literale Werte.05 · Selbst bauen
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 solltest du testen?
- 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.
Selbst ausprobieren
Formuliere die erste Prüfaussage als fehlschlagenden Test, implementiere die kleinste Korrektur und ergänze einen Grenzfall.
Aktives Locale, Fallback-Locale und fehlender Key werden getrennt geprüft.
Ansatz vergleichen
Dein Test sollte beim gezielten Verletzen der Invariante fehlschlagen und nach der Korrektur wieder bestehen. Halte den Aufbau deterministisch und prüfe ein beobachtbares Ergebnis.
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.
Eine Pluralnachrichtensyntax ist nicht implementiert. Für Datum, Zahlen und Pluralauswahl eignet sich Intl.
08 · Weiterdenken
Quellcode und verwandte Ideen
yarn tsx packages/i811n/examples/basic.ts