Zum Inhalt springen
5. Juli 20265 min readGuides

i18n-Pluralisierung: CLDR-Pluralregeln, i18next & ICU (Guide 2026)

Pluralisierung ist einer der am meisten unterschätzten Teile der Internationalisierung. Im Englischen wirkt sie trivial, ein Element gegenüber zwei Elementen, sodass die meisten Codebasen mit etwas wie count === 1 ? 'item' : 'items' beginnen. Diese eine Zeile ist in den meisten Sprachen der Welt ein Bug.

Dieser Guide erklärt, wie Plurale über die Sprachen hinweg tatsächlich funktionieren (via CLDR), wie i18next sie umsetzt, und die Handvoll Fehler, die Plural-Ausgaben in Produktion still kaputtmachen.

Inhaltsverzeichnis

Warum Pluralisierung schwierig ist

Englisch hat zwei Pluralformen: Singular (1 item) und Plural (0 items, 2 items, 100 items). Diese Zweiteilung ist die Ausnahme, nicht die Regel.

  • Japanisch, Chinesisch, Koreanisch: eine Form. Substantive ändern sich nicht mit der Menge.
  • Französisch: Der Singular deckt 0 und 1 ab, der Plural den Rest, plus eine separate Form für große formatierte Zahlen.
  • Polnisch, Russisch, Ukrainisch: Die Form für 2, 3, 4 unterscheidet sich von der für 5-21, die sich wiederum von 22-24 unterscheidet.
  • Arabisch: sechs verschiedene Formen, inklusive eigener Formen für 0, 1 und 2.

Das lässt sich nicht mit if (count === 1) ausdrücken. Die Regeln sind sprachspezifisch, nicht offensichtlich und von Linguisten definiert, nicht von Entwicklern. Dieses standardisierte Regelwerk ist CLDR.

CLDR-Pluralkategorien

Das Unicode CLDR definiert bis zu sechs Pluralkategorien. Jede Sprache ordnet jede Zahl genau einer davon zu:

KategorieBedeutung (variiert je nach Sprache)
zeroMenge 0 (nur einige Sprachen)
onesingularartige Menge
twoDual (nur einige Sprachen)
fewkleine Menge (sprachspezifisch)
manygroße Menge (sprachspezifisch)
otherAuffangkategorie / allgemeiner Plural

Wie viele eine Sprache tatsächlich nutzt:

SpracheVerwendete KategorienAnzahl
Japanisch, Chinesisch, Koreanischother1
Englisch, Deutsch, Spanisch, Italienischone, other2
Französischone, many, other3
Polnisch, Russisch, Ukrainischone, few, many, other4
Arabisch, Walisischzero, one, two, few, many, other6

Die gute Nachricht: Sie müssen sich das nicht merken. Der Browser bringt es mit. Intl.PluralRules liefert für jede Zahl und Locale die richtige Kategorie:

new Intl.PluralRules('en').select(1)   // "one"
new Intl.PluralRules('en').select(2)   // "other"
new Intl.PluralRules('pl').select(2)   // "few"
new Intl.PluralRules('pl').select(5)   // "many"
new Intl.PluralRules('ar').select(0)   // "zero"

Wie i18next Plurale behandelt

i18next v4 baut direkt auf Intl.PluralRules auf. Sie fügen pro benötigter Pluralkategorie einen JSON-Schlüssel hinzu und nutzen den Kategorienamen als Suffix:

{
  "item_one": "{{count}} item",
  "item_other": "{{count}} items"
}

Dann rufen Sie t() mit einem count auf:

t('item', { count: 1 })   // "1 item"
t('item', { count: 5 })   // "5 items"

i18next führt Intl.PluralRules(lng).select(count) aus, erhält die Kategorie (one, other, …) und löst item_<category> auf. Für eine Sprache, die mehr Formen braucht, stellen Sie einfach mehr Schlüssel bereit. Polnisch:

{
  "item_one": "{{count}} produkt",
  "item_few": "{{count}} produkty",
  "item_many": "{{count}} produktów",
  "item_other": "{{count}} produktu"
}

Im Code schreiben Sie denselben t('item', { count })-Aufruf; die richtige Form wird je nach aktiver Sprache gewählt. Genau das ist der Sinn der i18n-Pluralisierung: Die Logik lebt in den Daten, nicht in Ihren Komponenten.

Den count interpolieren

count dient zugleich als Interpolations-Wert, sodass {{count}} die Zahl in den String einsetzt:

{ "cart_one": "You have {{count}} item in your cart", "cart_other": "You have {{count}} items in your cart" }

Das Formatieren der Zahl (Tausendertrennzeichen usw.) ist ein separates, locale-abhängiges Thema und wird mit i18nexts format-Funktion oder Intl.NumberFormat erledigt. Behalten Sie Übersetzungsdateien als .json; siehe die Referenz JSON-Übersetzungsdateien für Struktur-Konventionen.

i18next v3 vs. v4 Plurale

Wenn Sie ältere Tutorials lesen oder ein Legacy-Projekt pflegen, sieht das Pluralformat anders aus. Das ist die mit Abstand häufigste Ursache für „meine Plurale funktionieren nicht mehr":

i18next v3i18next v4 (aktuell)
Sprachen mit zwei Formenkey + key_pluralkey_one + key_other
Sprachen mit mehreren Formenkey_0, key_1, key_2, …key_one, key_few, key_many, key_other
Quelle der Regelngebündelte JSON-Regelnnatives Intl.PluralRules

v4-Schlüssel sind selbsterklärend (das Suffix benennt die Kategorie) und bündeln keine Pluralregeltabelle mehr, was die Runtime kleiner hält. Ein v3-Projekt zu migrieren ist ein mechanisches Umbenennen; der offizielle Migrations-Guide und i18next-cli decken das ab.

Ordinale Plurale (1st, 2nd, 3rd)

Kardinalplurale (1 item) und Ordinalplurale (1st place) nutzen unterschiedliche CLDR-Regeln. i18next unterstützt Ordinalzahlen mit dem ordinal-Flag und _ordinal_*-Schlüsseln:

{
  "place_ordinal_one": "{{count}}st place",
  "place_ordinal_two": "{{count}}nd place",
  "place_ordinal_few": "{{count}}rd place",
  "place_ordinal_other": "{{count}}th place"
}
t('place', { count: 1, ordinal: true })   // "1st place"
t('place', { count: 3, ordinal: true })   // "3rd place"
t('place', { count: 11, ordinal: true })  // "11th place"

ICU-MessageFormat-Plurale

Wenn Sie einen einzelnen Inline-String gegenüber suffixierten Schlüsseln bevorzugen, ergänzt das Plugin i18next-icu ICU-MessageFormat-Unterstützung:

{ "item": "{count, plural, one {# item} other {# items}}" }

Beide Stile lösen unter der Haube zu denselben CLDR-Kategorien auf. Suffixierte Schlüssel sind der i18next-Standard (einfachere Diffs, ein String pro Form); ICU hält alles in einem String (dichter, vertraut für Teams, die von FormatJS/react-intl kommen). Wählen Sie einen und bleiben Sie konsistent.

ICU selbst wird von MessageFormat 2 (MF2) abgelöst, dem neuen Unicode-Standard (Final Candidate seit 2025), der Plurale über explizite .match-Selektoren ausdrückt und Kombinationen aus Genus und Plural sauberer behandelt. Die Verbreitung ist noch sehr gering, daher ist es noch nicht der pragmatische Standard. Ob sich der Einsatz heute lohnt, lesen Sie in MessageFormat 2 in i18next: Stand der Migration.

Wie sich i18nexts Format zu ICU, Fluent, Gettext und dem Rest des JS-Ökosystems verhält, zeigt I18N in the Multiverse of Formats.

Häufige Fehler

  • count als String übergeben. t('item', { count: '5' }) wählt nicht korrekt aus. Intl.PluralRules braucht eine Zahl.
  • Fehlende Kategorien. Nur _one und _other für eine Sprache bereitzustellen, die _few und _many braucht (Polnisch, Russisch), fällt still zurück und liest sich für Muttersprachler falsch.
  • v3/v4-Format-Mismatch. JSON im alten key_plural/key_0-Format gegen eine v4-Runtime (oder umgekehrt) löst zum Basisschlüssel oder zu nichts auf. Siehe v3 vs. v4.
  • Englische Regeln überall annehmen. 0 ist im Englischen _other, im Arabischen aber _zero. Behandeln Sie count === 0 nicht global als Sonderfall.
  • Ressourcen noch nicht geladen. Wenn Übersetzungen asynchron laden und Sie rendern, bevor sie ankommen, sehen Sie rohe Schlüssel, unabhängig von Pluralen. Siehe Übersetzungen werden nicht geladen.

Aktivieren Sie debug: true in Ihrer i18next-Konfiguration, um bei jedem Aufruf zu protokollieren, welcher Schlüssel aufgelöst wurde.

Plurale über Sprachen hinweg verwalten

Der schwierige Teil ist nicht der Code, sondern das richtige Set an Pluralformen für jede Sprache gefüllt zu halten. Wenn Sie Arabisch hinzufügen, müssen plötzlich sechs Formen pro pluralisiertem Schlüssel übersetzt werden; fügen Sie Japanisch hinzu, sind fünf davon überflüssig.

Genau hier verdient sich ein Translation-Management-System seinen Platz. Locize ist um das i18next-Pluralmodell herum gebaut:

  • Der Editor zeigt genau die Pluralformen, die jede Sprache benötigt, nicht mehr und nicht weniger, sodass Übersetzer _few für Polnisch nicht übersehen oder _two für Arabisch nicht leer lassen.
  • Plural-bewusste Validierung markiert Schlüssel, bei denen eine erforderliche Kategorie fehlt.
  • Neue Schlüssel, die via saveMissing hinzukommen, erhalten das korrekte Plural-Gerüst, bereit für menschliche oder KI-Übersetzung.

Bringen Sie die CLDR-Regeln einmal in Ordnung, und eine Sprache hinzuzufügen wird zur Übersetzungsaufgabe statt zur Engineering-Aufgabe, was das eigentliche Ziel von i18n ist.

Häufig gestellte Fragen

Wie behandelt i18next Plurale?

Sie rufen t(key, { count }) auf, und i18next hängt anhand der CLDR-Pluralkategorie dieses count für die aktive Sprache ein Suffix an, mithilfe des browsereigenen Intl.PluralRules. Im Englischen sind das ein _one- und ein _other-Schlüssel; in anderen Sprachen können es bis zu sechs Schlüssel sein (_zero, _one, _two, _few, _many, _other). Sie schreiben nie selbst eine count === 1-Logik.

Was sind CLDR-Pluralkategorien?

CLDR (das Unicode Common Locale Data Repository) definiert bis zu sechs Pluralkategorien: zero, one, two, few, many und other. Jede Sprache nutzt eine Teilmenge. Englisch verwendet one und other; Polnisch one, few, many, other; Arabisch alle sechs; Japanisch und Chinesisch nur other. Intl.PluralRules liefert für jede Zahl und Locale die richtige Kategorie.

Wie viele Pluralformen hat eine Sprache?

Zwischen einer und sechs. Japanisch, Chinesisch und Koreanisch haben eine (kein grammatischer Plural). Englisch, Deutsch, Spanisch und die meisten westeuropäischen Sprachen haben zwei. Französisch hat drei. Slawische Sprachen wie Polnisch und Russisch haben vier. Arabisch und Walisisch haben sechs. Deshalb scheitert eine boolesche Singular/Plural-Prüfung außerhalb des Englischen.

Was hat sich bei der Pluralisierung in i18next v4 geändert?

i18next v4 wechselte von numerischen Suffixen (key_0, key_1, key_2) und key_plural zu den CLDR-Kategorienamen (key_one, key_two, key_few, key_many, key_other), angetrieben von Intl.PluralRules. Damit sind Plural-Schlüssel selbsterklärend und konsistent mit dem Rest der Plattform. Bestehende v3-Projekte lassen sich mit dem offiziellen Migrations-Tooling umstellen.

Warum funktioniert mein i18next-Plural nicht?

Die üblichen Ursachen: Sie haben count als String statt als Zahl übergeben; dem Schlüssel fehlt das richtige CLDR-Suffix für die aktive Sprache (z. B. nur _one und _other, obwohl die Sprache _few und _many braucht); Ihr JSON ist noch im i18next-v3-Format, während die Runtime v4 ist (oder umgekehrt); oder die Sprachressourcen sind noch nicht fertig geladen. Aktivieren Sie debug: true, um zu sehen, welchen Schlüssel i18next aufgelöst hat.

Unterstützt i18next ordinale Plurale (1st, 2nd, 3rd)?

Ja. Übergeben Sie ordinal: true an t() und stellen Sie Ordinal-Schlüssel bereit (key_ordinal_one, key_ordinal_two, key_ordinal_few, key_ordinal_other). Im Englischen entsprechen sie 1st, 2nd, 3rd und 4th+. i18next nutzt Intl.PluralRules mit dem Typ "ordinal", um die richtige Form zu wählen.

Unterstützt i18next ICU-MessageFormat-Plurale?

Ja, über das Plugin i18next-icu. Damit können Sie ICU-Syntax wie {count, plural, one {# item} other {# items}} inline in einem einzigen String schreiben, statt suffixierte Schlüssel zu verwenden. Beide Ansätze nutzen dieselben zugrunde liegenden CLDR-Regeln; suffixierte Schlüssel sind der i18next-Standard, ICU ist optional.

Wie behandelt man eine „zero"-/Keine-Einträge-Meldung?

Für Sprachen, deren CLDR-Regeln eine zero-Kategorie enthalten (Arabisch, Lettisch, Walisisch), definieren Sie einen _zero-Schlüssel; er wird für count 0 automatisch verwendet. Für Sprachen ohne zero-Kategorie (wie Englisch, wo 0 zu _other aufgelöst wird) fügen Sie einen expliziten _zero-Schlüssel für eine dedizierte „Keine Einträge"-Meldung hinzu oder verzweigen vor dem t()-Aufruf über count === 0.