Wie man die richtige Pluralform für Bereiche wie 1-3 Artikel auswählt
Verwenden Sie JavaScript, um die korrekte Pluralform bei der Anzeige von Zahlenbereichen auszuwählen
Einführung
Bereiche kommunizieren, dass ein Wert zwischen zwei Endpunkten liegt. Benutzeroberflächen zeigen Bereiche in Kontexten wie Suchergebnissen mit "10-15 Treffer gefunden", Bestandssystemen mit "1-3 Artikel verfügbar" oder Filtern mit "Wählen Sie 2-5 Optionen". Diese Bereiche kombinieren zwei Zahlen mit beschreibendem Text, der grammatikalisch mit dem Bereich übereinstimmen muss.
Wenn Sie eine einzelne Anzahl anzeigen, wählen Sie zwischen Singular- und Pluralformen: "1 Artikel" versus "2 Artikel". Sprachen haben Regeln, die bestimmen, welche Form basierend auf der Anzahl angewendet wird. Diese Regeln variieren je nach Sprache. Englisch verwendet Singular für eins und Plural für alle anderen Zahlen. Polnisch verwendet unterschiedliche Formen für 1, 2-4 und 5 oder mehr. Arabisch hat sechs verschiedene Formen basierend auf der Anzahl.
Bereiche stellen eine andere Herausforderung dar. Die Pluralform hängt sowohl vom Start- als auch vom Endwert ab, nicht nur von einer einzelnen Zahl. Im Englischen verwendet "1-2 items" den Plural, obwohl der Bereich bei 1 beginnt. Verschiedene Sprachen haben unterschiedliche Regeln zur Bestimmung, welche Pluralform für einen Bereich gilt. Die Methode selectRange() bei Intl.PluralRules behandelt diese sprachspezifischen Regeln automatisch.
Warum Bereiche unterschiedliche Pluralisierungsregeln benötigen
Die Verwendung der Methode select() für eine einzelne Zahl aus einem Bereich funktioniert nicht korrekt für alle Sprachen. Man könnte denken, den Endwert des Bereichs zu verwenden, aber dies führt in vielen Sprachen zu falschen Ergebnissen.
Betrachten wir Englisch mit dem Bereich 0-1. Die Verwendung von select() für den Endwert gibt "one" zurück, was darauf hindeutet, dass Sie "0-1 item" anzeigen sollten. Dies ist grammatikalisch falsch. Die korrekte Form ist "0-1 items" mit dem Plural.
const rules = new Intl.PluralRules("en-US");
console.log(rules.select(1));
// Ausgabe: "one"
// Aber "0-1 item" ist falsch
// Korrekt: "0-1 items"
Verschiedene Sprachen haben explizite Regeln für Bereiche, die nicht mit ihren Regeln für einzelne Zahlen übereinstimmen. Im Slowenischen verwendet der Bereich 102-201 die Form "few", während einzelne Zahlen in diesem Bereich unterschiedliche Formen verwenden.
const slRules = new Intl.PluralRules("sl");
console.log(slRules.select(102));
// Ausgabe: "few"
console.log(slRules.select(201));
// Ausgabe: "few"
console.log(slRules.selectRange(102, 201));
// Ausgabe: "few"
Einige Sprachen verwenden den Startwert zur Bestimmung der Form, andere verwenden den Endwert, und wieder andere verwenden beide Werte zusammen. Die Methode selectRange() kapselt diese sprachspezifischen Regeln, sodass Sie sie nicht manuell implementieren müssen.
Erstellen einer PluralRules-Instanz für Bereiche
Erstellen Sie eine Intl.PluralRules-Instanz auf die gleiche Weise wie für einzelne Zahlen. Die Instanz bietet sowohl select() für einzelne Zahlen als auch selectRange() für Bereiche.
const rules = new Intl.PluralRules("en-US");
Sie können Optionen beim Erstellen der Instanz angeben. Diese Optionen gelten sowohl für einzelne Zahlen als auch für Bereiche.
const rules = new Intl.PluralRules("en-US", {
type: "cardinal"
});
Die Option type ist standardmäßig auf "cardinal" gesetzt, was das Zählen von Objekten behandelt. Sie können auch "ordinal" für Positionszahlen verwenden, obwohl Ordinalbereiche in Benutzeroberflächen weniger häufig vorkommen.
Verwenden Sie dieselbe Instanz für mehrere Aufrufe wieder. Eine neue Instanz für jede Pluralisierung zu erstellen ist ineffizient. Speichern Sie die Instanz in einer Variable oder cachen Sie sie nach Gebietsschema.
Verwenden von selectRange zur Bestimmung der Pluralkategorie für Bereiche
Die Methode selectRange() nimmt zwei Zahlen, die den Anfang und das Ende eines Bereichs darstellen. Sie gibt einen String zurück, der angibt, welche Pluralkategorie gilt: "zero", "one", "two", "few", "many" oder "other".
const rules = new Intl.PluralRules("en-US");
console.log(rules.selectRange(0, 1));
// Ausgabe: "other"
console.log(rules.selectRange(1, 2));
// Ausgabe: "other"
console.log(rules.selectRange(5, 10));
// Ausgabe: "other"
Im Englischen verwenden Bereiche fast immer die Kategorie "other", die der Pluralform entspricht. Dies entspricht der natürlichen Ausdrucksweise von Bereichen mit Pluralnomen bei englischen Sprechern.
Sprachen mit mehr Pluralformen geben je nach ihren spezifischen Regeln unterschiedliche Kategorien zurück.
const arRules = new Intl.PluralRules("ar-EG");
console.log(arRules.selectRange(0, 0));
// Ausgabe: "zero"
console.log(arRules.selectRange(1, 1));
// Ausgabe: "one"
console.log(arRules.selectRange(2, 2));
// Ausgabe: "two"
console.log(arRules.selectRange(3, 10));
// Ausgabe: "few"
Der Rückgabewert ist immer einer der sechs standardmäßigen Pluralkategorienamen. Ihr Code ordnet diese Kategorien dem entsprechenden lokalisierten Text zu.
Bereichskategorien auf lokalisierte Zeichenketten abbilden
Speichern Sie die Textformen für jede Pluralkategorie in einer Datenstruktur. Verwenden Sie die von selectRange() zurückgegebene Kategorie, um den entsprechenden Text nachzuschlagen.
const rules = new Intl.PluralRules("en-US");
const forms = new Map([
["one", "item"],
["other", "items"]
]);
function formatRange(start, end) {
const category = rules.selectRange(start, end);
const form = forms.get(category);
return `${start}-${end} ${form}`;
}
console.log(formatRange(1, 3));
// Output: "1-3 items"
console.log(formatRange(0, 1));
// Output: "0-1 items"
console.log(formatRange(5, 10));
// Output: "5-10 items"
Dieses Muster trennt die Pluralisierungslogik vom lokalisierten Text. Die Intl.PluralRules-Instanz verarbeitet die Sprachregeln. Die Map enthält die Übersetzungen. Die Funktion kombiniert sie.
Für Sprachen mit mehr Pluralkategorien fügen Sie Einträge für jede Kategorie hinzu, die die Sprache verwendet.
const arRules = new Intl.PluralRules("ar-EG");
const arForms = new Map([
["zero", "عناصر"],
["one", "عنصر"],
["two", "عنصران"],
["few", "عناصر"],
["many", "عنصرًا"],
["other", "عنصر"]
]);
function formatRange(start, end) {
const category = arRules.selectRange(start, end);
const form = arForms.get(category);
return `${start}-${end} ${form}`;
}
console.log(formatRange(0, 0));
// Output: "0-0 عناصر"
console.log(formatRange(1, 1));
// Output: "1-1 عنصر"
Stellen Sie immer Text für jede Kategorie bereit, die die Sprache verwendet. Überprüfen Sie die Unicode CLDR-Pluralregeln oder testen Sie mit der API über verschiedene Bereiche hinweg, um zu ermitteln, welche Kategorien benötigt werden.
Wie verschiedene Sprachversionen die Bereichspluralisierung handhaben
Jede Sprache hat ihre eigenen Regeln zur Bestimmung der Pluralform von Bereichen. Diese Regeln spiegeln wider, wie Muttersprachler Bereiche in dieser Sprache natürlich ausdrücken.
const enRules = new Intl.PluralRules("en-US");
console.log(enRules.selectRange(1, 3));
// Output: "other"
const slRules = new Intl.PluralRules("sl");
console.log(slRules.selectRange(102, 201));
// Output: "few"
const ptRules = new Intl.PluralRules("pt");
console.log(ptRules.selectRange(102, 102));
// Output: "other"
const ruRules = new Intl.PluralRules("ru");
console.log(ruRules.selectRange(1, 2));
// Output: "few"
Englisch verwendet konsequent "other" für Bereiche, wodurch Bereiche immer im Plural stehen. Slowenisch wendet komplexere Regeln an, die auf den spezifischen Zahlen im Bereich basieren. Portugiesisch verwendet "other" für die meisten Bereiche. Russisch verwendet "few" für bestimmte Bereiche.
Diese Unterschiede zeigen, warum fest codierte Plurallogik für internationale Anwendungen versagt. Die API kapselt das Wissen darüber, wie jede Sprache mit Bereichen umgeht.
Kombination mit Intl.NumberFormat für vollständige Formatierung
Reale Anwendungen müssen sowohl die Zahlen als auch den Text formatieren. Verwenden Sie Intl.NumberFormat, um die Bereichsendpunkte gemäß den Locale-Konventionen zu formatieren, und dann selectRange(), um die korrekte Pluralform auszuwählen.
const locale = "en-US";
const numberFormat = new Intl.NumberFormat(locale);
const pluralRules = new Intl.PluralRules(locale);
const forms = new Map([
["one", "item"],
["other", "items"]
]);
function formatRange(start, end) {
const startFormatted = numberFormat.format(start);
const endFormatted = numberFormat.format(end);
const category = pluralRules.selectRange(start, end);
const form = forms.get(category);
return `${startFormatted}-${endFormatted} ${form}`;
}
console.log(formatRange(1, 3));
// Output: "1-3 items"
console.log(formatRange(1000, 5000));
// Output: "1,000-5,000 items"
Der Zahlenformatierer fügt Tausendertrennzeichen hinzu. Die Pluralregeln wählen die korrekte Form aus. Die Funktion kombiniert beides, um korrekt formatierte Ausgaben zu erzeugen.
Verschiedene Locales verwenden unterschiedliche Zahlenformatierungskonventionen.
const locale = "de-DE";
const numberFormat = new Intl.NumberFormat(locale);
const pluralRules = new Intl.PluralRules(locale);
const forms = new Map([
["one", "Artikel"],
["other", "Artikel"]
]);
function formatRange(start, end) {
const startFormatted = numberFormat.format(start);
const endFormatted = numberFormat.format(end);
const category = pluralRules.selectRange(start, end);
const form = forms.get(category);
return `${startFormatted}-${endFormatted} ${form}`;
}
console.log(formatRange(1000, 5000));
// Output: "1.000-5.000 Artikel"
Deutsch verwendet Punkte als Tausendertrennzeichen anstelle von Kommas. Der Zahlenformatierer behandelt dies automatisch. Die Pluralregeln bestimmen, welche Form von "Artikel" verwendet werden soll.
Vergleich von selectRange mit select für einzelne Werte
Die Methode select() behandelt einzelne Zählungen, während selectRange() Bereiche behandelt. Verwenden Sie select(), wenn Sie eine einzelne Menge anzeigen, und selectRange(), wenn Sie einen Bereich zwischen zwei Werten anzeigen.
const rules = new Intl.PluralRules("en-US");
// Einzelne Zählung
console.log(rules.select(1));
// Ausgabe: "one"
console.log(rules.select(2));
// Ausgabe: "other"
// Bereich
console.log(rules.selectRange(1, 2));
// Ausgabe: "other"
console.log(rules.selectRange(0, 1));
// Ausgabe: "other"
Für einzelne Zählungen hängen die Regeln nur von dieser einen Zahl ab. Für Bereiche berücksichtigen die Regeln beide Endpunkte. Im Englischen verwendet ein Bereich, der bei 1 beginnt, immer noch die Pluralform, obwohl die einzelne Zahl 1 die Singularform verwendet.
Einige Sprachen zeigen dramatischere Unterschiede zwischen Regeln für einzelne Zählungen und Regeln für Bereiche.
const slRules = new Intl.PluralRules("sl");
// Einzelne Zählungen im Slowenischen
console.log(slRules.select(1));
// Ausgabe: "one"
console.log(slRules.select(2));
// Ausgabe: "two"
console.log(slRules.select(5));
// Ausgabe: "few"
// Bereich im Slowenischen
console.log(slRules.selectRange(102, 201));
// Ausgabe: "few"
Slowenisch verwendet "one", "two" und "few" für verschiedene einzelne Zählungen basierend auf komplexen Regeln. Für Bereiche wendet es eine andere Logik an, die beide Zahlen zusammen berücksichtigt.
Umgang mit Bereichen, bei denen Anfang und Ende gleich sind
Wenn Anfangs- und Endwerte gleich sind, zeigen Sie einen Bereich ohne Breite an. Einige Anwendungen verwenden dies, um einen exakten Wert in einem Kontext darzustellen, in dem Bereiche erwartet werden.
const rules = new Intl.PluralRules("en-US");
console.log(rules.selectRange(5, 5));
// Ausgabe: "other"
console.log(rules.selectRange(1, 1));
// Ausgabe: "one"
Wenn beide Werte gleich 1 sind, gibt Englisch "one" zurück, was darauf hindeutet, dass Sie die Singularform verwenden sollten. Wenn beide Werte eine andere Zahl sind, gibt Englisch "other" zurück, was die Pluralform nahelegt.
Dieses Verhalten ist sinnvoll, wenn Sie den Bereich als "1-1 item" oder einfach "1 item" anzeigen. Für andere Werte als 1 zeigen Sie "5-5 items" oder "5 items" an.
In der Praxis möchten Sie möglicherweise erkennen, wann Anfang gleich Ende ist, und einen einzelnen Wert anstelle eines Bereichs anzeigen.
const rules = new Intl.PluralRules("en-US");
const forms = new Map([
["one", "item"],
["other", "items"]
]);
function formatRange(start, end) {
if (start === end) {
const category = rules.select(start);
const form = forms.get(category);
return `${start} ${form}`;
}
const category = rules.selectRange(start, end);
const form = forms.get(category);
return `${start}-${end} ${form}`;
}
console.log(formatRange(1, 1));
// Ausgabe: "1 item"
console.log(formatRange(5, 5));
// Ausgabe: "5 items"
console.log(formatRange(1, 3));
// Ausgabe: "1-3 items"
Dieser Ansatz verwendet select() für gleiche Werte und selectRange() für tatsächliche Bereiche. Die Ausgabe liest sich natürlicher, da sie die Anzeige von "1-1" oder "5-5" vermeidet.
Umgang mit Sonderfällen bei selectRange
Die Methode selectRange() validiert ihre Eingaben. Wenn einer der Parameter undefined, null ist oder nicht in eine gültige Zahl umgewandelt werden kann, wirft die Methode einen Fehler.
const rules = new Intl.PluralRules("en-US");
try {
console.log(rules.selectRange(1, undefined));
} catch (error) {
console.log(error.name);
// Ausgabe: "TypeError"
}
try {
console.log(rules.selectRange(NaN, 5));
} catch (error) {
console.log(error.name);
// Ausgabe: "RangeError"
}
Validieren Sie Ihre Eingaben, bevor Sie sie an selectRange() übergeben. Dies ist besonders wichtig, wenn Sie mit Benutzereingaben oder Daten aus externen Quellen arbeiten.
function formatRange(start, end) {
if (typeof start !== "number" || typeof end !== "number") {
throw new Error("Start and end must be numbers");
}
if (isNaN(start) || isNaN(end)) {
throw new Error("Start and end must be valid numbers");
}
const category = rules.selectRange(start, end);
const form = forms.get(category);
return `${start}-${end} ${form}`;
}
Die Methode akzeptiert Zahlen, BigInt-Werte oder Strings, die als Zahlen geparst werden können.
const rules = new Intl.PluralRules("en-US");
console.log(rules.selectRange(1, 5));
// Ausgabe: "other"
console.log(rules.selectRange(1n, 5n));
// Ausgabe: "other"
console.log(rules.selectRange("1", "5"));
// Ausgabe: "other"
String-Eingaben werden als Zahlen geparst. Dies ermöglicht Flexibilität bei der Aufrufweise der Methode, aber Sie sollten aus Gründen der Klarheit vorzugsweise tatsächliche Zahlentypen übergeben.
Umgang mit Dezimalbereichen
Die Methode selectRange() funktioniert mit Dezimalzahlen. Dies ist nützlich bei der Anzeige von Bereichen mit Bruchmengen wie Messungen oder Statistiken.
const rules = new Intl.PluralRules("en-US");
console.log(rules.selectRange(1.5, 2.5));
// Ausgabe: "other"
console.log(rules.selectRange(0.5, 1.0));
// Ausgabe: "other"
console.log(rules.selectRange(1.0, 1.5));
// Ausgabe: "other"
Im Englischen werden alle diese Dezimalbereiche als Plural behandelt. Andere Sprachen können unterschiedliche Regeln für Dezimalbereiche haben.
Bei der Formatierung von Dezimalbereichen kombinieren Sie selectRange() mit Intl.NumberFormat, das für die entsprechende Dezimalpräzision konfiguriert ist.
const locale = "en-US";
const numberFormat = new Intl.NumberFormat(locale, {
minimumFractionDigits: 1,
maximumFractionDigits: 1
});
const pluralRules = new Intl.PluralRules(locale);
const forms = new Map([
["one", "kilometer"],
["other", "kilometers"]
]);
function formatRange(start, end) {
const startFormatted = numberFormat.format(start);
const endFormatted = numberFormat.format(end);
const category = pluralRules.selectRange(start, end);
const form = forms.get(category);
return `${startFormatted}-${endFormatted} ${form}`;
}
console.log(formatRange(1.5, 2.5));
// Ausgabe: "1.5-2.5 kilometers"
console.log(formatRange(0.5, 1.0));
// Ausgabe: "0.5-1.0 kilometers"
Der Number-Formatter sorgt für eine konsistente Dezimalanzeige. Die Pluralregeln bestimmen die korrekte Form basierend auf den Dezimalwerten.
Browser-Unterstützung und Kompatibilität
Die Methode selectRange() ist im Vergleich zum Rest der Intl-API relativ neu. Sie wurde 2023 als Teil der Intl.NumberFormat v3-Spezifikation verfügbar.
Die Browser-Unterstützung umfasst Chrome 106 und höher, Firefox 116 und höher, Safari 15.4 und höher sowie Edge 106 und höher. Die Methode ist in Internet Explorer oder älteren Browser-Versionen nicht verfügbar.
Für Anwendungen, die auf moderne Browser abzielen, können Sie selectRange() ohne Polyfill verwenden. Wenn Sie ältere Browser unterstützen müssen, überprüfen Sie vor der Verwendung, ob die Methode existiert.
const rules = new Intl.PluralRules("en-US");
if (typeof rules.selectRange === "function") {
// selectRange für Bereichspluralisierung verwenden
console.log(rules.selectRange(1, 3));
} else {
// Fallback auf select mit dem Endwert
console.log(rules.select(3));
}
Dieser Fallback-Ansatz verwendet select() auf dem Endwert, wenn selectRange() nicht verfügbar ist. Dies ist linguistisch nicht perfekt für alle Sprachen, bietet aber eine vernünftige Annäherung für ältere Browser.
Polyfills sind über Pakete wie @formatjs/intl-pluralrules verfügbar, wenn Sie umfassende Unterstützung für ältere Umgebungen benötigen.
Wann man selectRange versus select verwenden sollte
Verwenden Sie selectRange(), wenn Ihre Benutzeroberfläche explizit einen Bereich anzeigt, bei dem sowohl Start- als auch Endwerte für den Benutzer sichtbar sind. Dies umfasst Kontexte wie Suchergebnisse, die "10-15 Übereinstimmungen gefunden" anzeigen, Lagerbestand mit "1-3 Artikel auf Lager" oder Filter mit "Wählen Sie 2-5 Optionen".
Verwenden Sie select(), wenn Sie eine einzelne Anzahl anzeigen, auch wenn diese Anzahl einen ungefähren oder zusammengefassten Wert darstellt. Zum Beispiel verwendet "Etwa 10 Ergebnisse" select(10), weil Sie eine einzelne Zahl anzeigen und keinen Bereich.
Wenn Ihr Bereich mit Intl.NumberFormat.formatRange() für die Zahlen angezeigt wird, verwenden Sie selectRange() für den begleitenden Text. Dies gewährleistet Konsistenz zwischen der Zahlenformatierung und der Pluralisierung des Textes.
const locale = "en-US";
const numberFormat = new Intl.NumberFormat(locale);
const pluralRules = new Intl.PluralRules(locale);
const forms = new Map([
["one", "result"],
["other", "results"]
]);
function formatSearchResults(start, end) {
const rangeFormatted = numberFormat.formatRange(start, end);
const category = pluralRules.selectRange(start, end);
const form = forms.get(category);
return `Found ${rangeFormatted} ${form}`;
}
console.log(formatSearchResults(10, 15));
// Output: "Found 10–15 results"
Dieses Muster verwendet formatRange() von Intl.NumberFormat zur Formatierung der Zahlen und selectRange() von Intl.PluralRules zur Auswahl des Textes. Beide Methoden arbeiten mit Bereichen und gewährleisten so eine korrekte Handhabung für alle Sprachen.