EnglishGitHub
teilweisepackages/i811n/src

i811n

@ralphschuler/i811n

Löst Sprachkataloge auf und ersetzt Platzhalter durch literale Werte.

localizationinterpolationIntl

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.

Im Repository

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?

  1. Aktives und Fallback-Locale gegen den Katalog prüfen.
  2. Template erst im aktiven, dann im Fallback-Katalog suchen.
  3. Bekannte Platzhalter über einen festen Parser ersetzen.
  4. 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.

  1. Validiere initiales und neues Locale gegen vorhandene Kataloge.
  2. Implementiere eine klare Fallback-Kette für fehlende Keys.
  3. Delegiere Zahl, Datum und Pluralisierung an Intl statt eigene Regeln zu erfinden.
Konzeptskizze · kann ausgelassene Helfer verwenden
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.
Wichtig

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