12k
All articles

Internationalisierung einer React-App hinzufügen

Richten Sie Internationalisierung in React mit react-i18next ein: Interpolation, Pluralisierung, RTL-Layout, Locale-Formatierung und Next.js-SSR.

OpenReplay Team
OpenReplay Team
Internationalisierung einer React-App hinzufügen

Internationalisierung in eine React-App einzubauen bedeutet, alle benutzerseitigen Zeichenketten in sprachspezifische Dateien auszulagern und sie über eine Übersetzungsschicht zu rendern, anstatt Text direkt in JSX zu kodieren.

Wenn Sie schon einmal einen Build ausgeliefert haben, bei dem ein roher t('main.header') auf dem Bildschirm eines Kunden erschien, oder erlebt haben, wie ein deutscher String einen Button sprengte, der auf Englisch noch tadellos aussah, wissen Sie bereits: Die Einrichtung ist nicht das Problem. Die Verkabelung kostet einen Nachmittag; die lokalisierungsspezifischen Sonderfälle fressen den Rest des Sprints. Der produktionsreife Standard dafür ist react-i18next, die React-Anbindung an das i18next-Framework. Setzen Sie auf react-i18next: Es basiert auf Hooks, unterstützt Namespaces und Lazy Loading, funktioniert mit Server-Side Rendering und profitiert vom größten i18next-Plugin-Ökosystem. Greifen Sie nur dann zu react-intl, wenn Sie sich bewusst für die ICU-Message-Syntax entscheiden. Dieser Leitfaden behandelt die korrekte aktuelle Einrichtung sowie die fünf häufigsten Stolperfallen in der Produktion: Interpolation, Pluralisierung, lokalisierungsbewusste Zahlen- und Datumsformatierung, Rechts-nach-links-Layout und SSR.

Wichtige Erkenntnisse

  • Setzen Sie interpolation.escapeValue: false in Ihrer i18next-Konfiguration, da React Werte vor dem Rendering bereits escaped; bleibt das Escaping von i18next aktiv, werden Ihre Zeichenketten doppelt escaped.
  • In aktuellem i18next verwenden Plural-Keys CLDR/Intl-Suffixe (_zero, _one, _two, _few, _many, _other); das Legacy-Suffix _plural gehört zum alten JSON-v3-Format. Die auswählende Variable muss count heißen.
  • Zahlen- und Datumsformatierung hängt von der Region ab, nicht nur von der Sprache – qualifizieren Sie daher Locales (en-US, ar-EG) und formatieren Sie mit i18next’s Intl-Formatierern über {{value, number}} und {{date, datetime}}.
  • Laden Sie Übersetzungen aus JSON-Dateien mit i18next-http-backend und einem loadPath; das Einbetten per require() packt alle Sprachen in Ihr Haupt-Bundle und verhindert Lazy Loading.
  • Auf Next.js sollten Sie SSR-i18n nicht manuell verdrahten: next-i18next v16 bindet sowohl den App Router als auch den Pages Router in einem einzigen Paket ein.

Wie richtet man react-i18next ein?

Installieren Sie das Core-Framework, die React-Anbindung und zwei Plugins für Spracherkennung und Dateiladen. Vier Pakete tragen die Einrichtung, jedes mit einer klar definierten Aufgabe:

PaketVersionsreiheZweck
i18next26.xCore-Engine: Lookup, Interpolation, Plurale, Formatierung
react-i18next17.xReact-Anbindung: useTranslation, Trans
i18next-browser-languagedetector8.xErkennt die Sprache des Benutzers
i18next-http-backend4.xLädt Übersetzungs-JSON per HTTP

Ein wichtiger Hinweis: i18next-http-backend v4 setzt natives fetch voraus. Node ≥ 18, alle modernen Browser, Deno und Bun liefern fetch standardmäßig mit. Auf älteren Laufzeitumgebungen müssen Sie einen Ponyfill bereitstellen oder bei v3 bleiben.

npm install i18next react-i18next i18next-browser-languagedetector i18next-http-backend

Erstellen Sie src/i18n.ts und initialisieren Sie einmalig:

import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    supportedLngs: ['en', 'es', 'ar'],
    load: 'languageOnly',
    backend: { loadPath: '/locales/{{lng}}/{{ns}}.json' },
    interpolation: { escapeValue: false },
  });

export default i18n;

Setzen Sie interpolation.escapeValue: false, da React Werte vor dem Rendering bereits escaped; bleibt das Escaping von i18next aktiv, werden Ihre Zeichenketten doppelt escaped. Der loadPath ist entscheidend: Das Einbetten von Ressourcen per require() – ein Muster aus der Create-React-App/Webpack-Ära – packt alle Sprachen in Ihr Haupt-Bundle und verhindert Lazy Loading. Importieren Sie die Konfiguration einmalig an Ihrem Einstiegspunkt, vor dem Rendering: import './i18n'; in main.tsx.

Zeichenketten mit dem useTranslation-Hook auslagern

Übersetzungen liegen in sprachspezifischen JSON-Dateien unter public/locales/<lng>/translation.json, und Komponenten lesen sie über die t-Funktion des useTranslation-Hooks. Ersetzen Sie jede fest kodierte Zeichenkette durch einen Key-Lookup.

{ "main": { "header": "Willkommen in der App!" } }
import { useTranslation } from 'react-i18next';

export default function Header() {
  const { t } = useTranslation();
  return <h1>{t('main.header')}</h1>;
}

Verschachtelte Keys (main.header) und Namespaces strukturieren umfangreiche Zeichenkettensätze. Für Texte, die Inline-Markup oder Links enthalten, stößt der einfache t()-Aufruf an seine Grenzen. Verwenden Sie stattdessen die Trans-Komponente, die React-Elemente in einen übersetzten Satz interpoliert und das Markup dabei in Ihrer Komponente belässt – nicht in Ihrem JSON.

<Trans i18nKey="main.docs" components={{ docsLink: <a href="https://react.i18next.com/" /> }} />

Wie wechselt und erkennt man Sprachen?

Wechseln Sie die aktive Sprache mit i18n.changeLanguage(lng); jede Komponente, die useTranslation verwendet, rendert automatisch neu. Ein Sprachumschalter besteht schlicht aus Buttons oder einem <select>, das diese Methode aufruft:

const { i18n } = useTranslation();
<select
  value={i18n.resolvedLanguage}
  onChange={(e) => i18n.changeLanguage(e.target.value)}
>
  <option value="en">English</option>
  <option value="ar">العربية</option>
</select>

Die Erkennung übernimmt das Language-Detector-Plugin, das Quellen in einer festen Reihenfolge prüft: Query-String (?lng=en), ein Cookie, localStorage, den Browser-navigator und schließlich das <html lang>-Attribut. Es stoppt beim ersten unterstützten Treffer. Die ermittelte Sprache wird in localStorage gespeichert, sodass wiederkehrende Benutzer ihre Wahl behalten; ein manueller changeLanguage-Aufruf aktualisiert diesen Cache ebenfalls.

Die fünf häufigsten Stolperfallen

Die meisten i18n-Fehler lauern abseits des Standardpfads. Das sind die Fehlerszenarien, die lokale QA-Tests bestehen und erst in der Locale eines echten Benutzers auftauchen.

Interpolation. Injizieren Sie dynamische Werte mit der {{var}}-Syntax und übergeben Sie sie als zweites Argument: t('greeting', { name }) gegen "Hallo, {{name}}". Reacts Escaping in Kombination mit escapeValue: false hält dies XSS-sicher.

Pluralisierung. Englisch benötigt zwei Pluralformen, Arabisch sechs – genau deshalb schreibt man niemals manuell if (count === 1). Übergeben Sie count an t() und lassen Sie Intl.PluralRules den passenden Key auswählen. Definieren Sie Formen mit CLDR-Suffixen: _zero, _one, _two, _few, _many, _other. Die Variable muss zwingend count heißen.

{
  "messages_one": "Sie haben eine neue Nachricht",
  "messages_other": "Sie haben {{count}} neue Nachrichten"
}

Das alte Suffix _plural ist Legacy-JSON-v3. i18next hat seine Plural-Suffixe vereinheitlicht, um sie an die der Intl-API anzupassen, als das JSON-v4-Format eingeführt wurde. Seit v24 ist die Intl-API verpflichtend: Fehlt Intl.PluralRules in Ihrer Laufzeitumgebung, müssen Sie einen Polyfill bereitstellen, da der alte Fallback auf v3-Plural-Handling entfernt wurde und compatibilityJSON 'v3' nicht mehr akzeptiert.

Zahlen- und Datumsformatierung. Formatieren Sie mit i18next’s eingebauten Intl-Formatierern: {{value, number}} und {{date, datetime}}, mit Optionen wie {{value, number(style: percent)}}. Da die Formatierung von der Region abhängt, qualifizieren Sie Ihre Locales (en-US, ar-EG), damit Zifferndarstellung und Datumsreihenfolge browserübergreifend konsistent bleiben.

Rechts-nach-links. Für RTL-Sprachen setzen Sie die Dokumentrichtung über i18n.dir() bei jedem Sprachwechsel, damit das gesamte Layout neu fließt – ohne CSS-Anpassungen pro Komponente:

useEffect(() => {
  const apply = (lng: string) => {
    document.documentElement.lang = lng;
    document.documentElement.dir = i18n.dir(lng);
  };
  i18n.on('languageChanged', apply);
  return () => i18n.off('languageChanged', apply);
}, [i18n]);

Lesen Sie i18n.dir() innerhalb des languageChanged-Handlers aus, nicht synchron mitten im Wechsel: Nach changeLanguage() spiegelt i18next.language die neue Sprache erst wider, sobald die Ressourcen geladen sind.

SSR. Verdrahten Sie Server-seitiges i18n auf Next.js nicht manuell. next-i18next v16 ist eine schlanke Schicht über i18next und react-i18next, die die Next.js-spezifische Verkabelung übernimmt: Middleware, die Server/Client-Aufteilung und die Ressourcen-Hydration. Es unterstützt den App Router (Server Components, Client Components, Middleware) und den Pages Router, mit getT() für Server Components und useT() für Client Components. Wrappen Sie Client-Bäume in <Suspense>, anstatt das Vorhandensein von window vorauszusetzen. Genau diese lokalisierungsspezifischen Defekte – ein roher Key wie main.header, der dem Benutzer angezeigt wird, RTL-Padding, das Text abschneidet, oder Fallback-Sprachtexte, die in einen übersetzten Screen durchsickern – sind es, die Standard-Locale-QA-Tests bestehen und erst sichtbar werden, wenn Sie eine echte Session in der Zielsprache beobachten. Genau hier zahlt sich Session Replay aus.

Mit Namespaces und Key-Extraktion skalieren

Wenn die Anzahl der Zeichenketten wächst, teilen Sie Übersetzungen in Namespaces auf und laden Sie diese pro Route mit useTranslation('dashboard'), sodass jede Seite nur ihr eigenes JSON abruft und die Bundles klein bleiben. Sobald sich Zeichenketten über die gesamte Codebasis verteilen, greifen Sie zu automatisierten Werkzeugen: i18next-cli ist das offizielle, umfassende Kommandozeilen-Tool, das Key-Extraktion, Code-Linting, Locale-Synchronisierung und Typgenerierung übernimmt. Ein Translation-Management-System wie Lokalise, Phrase oder Crowdin koordiniert Übersetzer, sobald die eigentliche Lokalisierungsarbeit beginnt.

Sie verfügen nun über eine korrekte react-i18next-Einrichtung und einen Überblick über die weiterführenden Themen. Verdrahten Sie die Konfiguration, lagern Sie Ihre Zeichenketten aus, greifen Sie zu Namespaces, wenn Bundles wachsen, und zu next-i18next, wenn Sie serverseitig rendern. Überprüfen Sie bei der Installation die genauen Paketversionen auf npm, da i18next-Core und Bindings regelmäßig aktualisiert werden.

FAQs

Was ist der Unterschied zwischen i18next und react-i18next?

i18next ist das Core-Framework, das die eigentliche Übersetzungslogik übernimmt: Key-Lookup, Interpolation, Pluralisierung und Formatierung. react-i18next ist die darüber liegende React-Anbindung, die Hooks wie useTranslation, die Trans-Komponente und automatisches Re-Rendering bei Sprachwechseln bereitstellt. Sie installieren beide: i18next erledigt die Arbeit, react-i18next verbindet es mit Ihren Komponenten. react-i18next setzt ein modernes i18next als Peer voraus – halten Sie beide auf kompatiblen Major-Versionen.

Warum wird mein Übersetzungs-Key als Literal-Text angezeigt statt als übersetzte Zeichenkette?

Ein roher Key wie main.header, der dem Benutzer angezeigt wird, bedeutet, dass der Lookup fehlgeschlagen ist – fast immer, weil die JSON-Datei für diese Sprache oder diesen Namespace nie geladen wurde. Häufige Ursachen: ein loadPath, der nicht mit Ihrem Dateipfad übereinstimmt, ein nicht registrierter Namespace, eine i18n-Konfiguration, die nicht vor dem Rendering importiert wurde, oder ein Key, der in der Datei nicht existiert. Prüfen Sie den Netzwerk-Tab auf fehlgeschlagene Anfragen an Ihren Locales-Pfad und vergewissern Sie sich, dass der Key in der korrekten Sprachdatei vorhanden ist.

Verwende ich in i18next noch das Suffix _plural für Plural-Keys?

Nein. Das Suffix _plural gehört zum Legacy-JSON-v3-Format. Aktuelles i18next verwendet CLDR/Intl-Wortsuffixe, die Intl.PluralRules entsprechen: _zero, _one, _two, _few, _many und _other. Englisch verwendet zwei Formen (_one und _other), Arabisch alle sechs. Die Variable, die die Form auswählt, muss count heißen und muss vorhanden sein, da es keinen Fallback gibt, wenn count fehlt. Ist Intl.PluralRules nicht verfügbar, müssen Sie einen Polyfill bereitstellen: Seit v24 gibt es keinen Fallback mehr auf das alte v3-Plural-Handling, und compatibilityJSON akzeptiert v3 nicht mehr.

Muss ich Übersetzungen in JSON-Dateien speichern oder kann ich sie in der Konfiguration einbetten?

Sie können Übersetzungen über die resources-Option einbetten, aber für alles jenseits einer trivialen App sollten Sie sie aus JSON-Dateien mit i18next-http-backend und einem loadPath wie /locales/{{lng}}/{{ns}}.json laden. Das Einbetten aller Sprachen per require() packt alle Übersetzungen in Ihr Haupt-Bundle und verhindert Lazy Loading – Benutzer laden damit Zeichenketten für Sprachen herunter, die sie nie verwenden. Dateibasiertes Laden ruft nur die aktive Sprache und den aktiven Namespace bei Bedarf ab. Beachten Sie, dass i18next-http-backend v4 natives fetch voraussetzt, also Node 18 oder neuer.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.