Zum Inhalt

i18n-Implementierung

KanjiIQ verwendet Flutters eingebautes Internationalisierungs-Framework mit ARB-Dateien (Application Resource Bundle) für die UI-Lokalisierung und PostgreSQL JSONB für die Inhaltslokalisierung.

UI-Lokalisierung mit ARB

Konfiguration

Das Lokalisierungssystem wird in frontend/l10n.yaml konfiguriert:

arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart

ARB-Dateistruktur

Jede Sprache hat eine ARB-Datei im ICU-Nachrichtenformat:

// lib/l10n/app_en.arb (template)
{
  "@@locale": "en",
  "appTitle": "KanjiIQ",
  "studyButton": "Start Study",
  "selectLanguage": "Select Language",
  "selectLevel": "Select JLPT Level",
  "cardCount": "{count} cards",
  "@cardCount": {
    "placeholders": {
      "count": { "type": "int" }
    }
  },
  "noConnection": "No internet connection. Using cached data.",
  "showAllLanguages": "Show all 51 languages"
}

Codegenerierung

Das Ausführen von flutter gen-l10n generiert:

  • app_localizations.dart — Abstrakte Basisklasse mit allen lokalisierten Zeichenketten
  • app_localizations_en.dart — Englische Implementierung
  • app_localizations_ja.dart — Japanische Implementierung
  • ... (51 generierte Dateien)

Verwendung in Flutter-Widgets:

// Access localized strings
Text(AppLocalizations.of(context)!.studyButton)

// With parameters
Text(AppLocalizations.of(context)!.cardCount(10))

Registrierung unterstützter Locales

Locales werden in MaterialApp registriert:

MaterialApp(
  localizationsDelegates: AppLocalizations.localizationsDelegates,
  supportedLocales: AppLocalizations.supportedLocales,
  locale: selectedLocale,  // From LocalePreferences
)

Inhaltslokalisierung

Karteikarten-Inhalte (Kanji-Bedeutungen, Vokabeldefinitionen) werden als JSONB in PostgreSQL gespeichert und über die API bereitgestellt:

graph LR
    A[API Request<br/>?lang=pt] --> B[Backend]
    B --> C[PostgreSQL<br/>JSONB lookup]
    C --> D[Return meaning<br/>in Portuguese]

Übersetzungs-Pipeline

Neue Inhalte werden über die OpenAI API übersetzt:

  1. Quellinhalte werden auf Englisch verfasst
  2. Das Backend sendet Übersetzungsanfragen an OpenAI mit Kontext zu JLPT-Stufe und Verwendung
  3. Übersetzungen werden in der JSONB-Spalte neben bestehenden Übersetzungen gespeichert
  4. Jede Sprache kann unabhängig aktualisiert werden, ohne andere zu beeinflussen

Selbst gehostete Übersetzung

Die Kubernetes-Manifeste enthalten ein LibreTranslate-Deployment (k8s/04-libretranslate-deployment.yaml) als Alternative zu OpenAI. Dies bietet vollständig selbst gehostete Übersetzung ohne externe API-Abhängigkeiten, obwohl die Qualität je nach Sprachpaar variiert.

UI- vs. Inhaltssprache

KanjiIQ erlaubt es, dass die UI-Sprache und die Lernsprache unterschiedlich sind:

  • UI-Sprache: Die Sprache der Schaltflächen, Beschriftungen und Navigation (z.B. Französisch)
  • Lernsprache: Die Sprache für Karteikarten-Bedeutungen (z.B. Portugiesisch)

Ein französischsprachiger Benutzer, der Japanisch lernt, kann die Oberfläche auf Französisch haben, während er Karteikarten-Bedeutungen auf Portugiesisch sieht, wenn er dies bevorzugt.

Eine neue Sprache hinzufügen

Um eine neue (52.) Sprache hinzuzufügen:

  1. UI: lib/l10n/app_XX.arb mit allen übersetzten Zeichenketten erstellen
  2. Inhalt: Übersetzungen über die Übersetzungs-Pipeline zu JSONB-Spalten hinzufügen
  3. Locale-Konfiguration: Den Sprachcode über die Admin-API zu relevanten locale_configs-Einträgen hinzufügen
  4. Build: flutter gen-l10n ausführen, um Lokalisierungsdateien neu zu generieren

Keine Schemamigrationen oder Backend-Code-Änderungen erforderlich — der JSONB-Speicher und das ARB-System sind beide auf Erweiterbarkeit ausgelegt.