Alle verfügbaren Pluralformen in einer Locale abrufen
Entdecken Sie, welche Pluralkategorien Sie für Übersetzungen bereitstellen müssen
Einführung
Beim Erstellen mehrsprachiger Anwendungen müssen Sie verschiedene Textformen für unterschiedliche Mengen bereitstellen. Im Englischen schreibt man "1 item" und "2 items". Dies erscheint einfach, bis Sie beginnen, andere Sprachen zu unterstützen.
Russisch verwendet drei verschiedene Formen abhängig von der Anzahl. Arabisch verwendet sechs. Einige Sprachen verwenden die gleiche Form für alle Anzahlen. Bevor Sie Übersetzungen für diese Formen bereitstellen können, müssen Sie wissen, welche Formen in jeder Sprache existieren.
JavaScript bietet eine Möglichkeit, herauszufinden, welche Pluralkategorien eine Locale verwendet. Die Methode resolvedOptions() einer PluralRules-Instanz gibt eine Eigenschaft pluralCategories zurück, die alle Pluralformen auflistet, die die Locale benötigt. Dies teilt Ihnen genau mit, welche Übersetzungen bereitzustellen sind, ohne zu raten oder sprachspezifische Regeltabellen zu pflegen.
Was Pluralkategorien sind
Pluralkategorien sind standardisierte Namen für verschiedene Pluralformen, die in verschiedenen Sprachen verwendet werden. Das Unicode CLDR (Common Locale Data Repository) definiert sechs Kategorien: zero, one, two, few, many und other.
Nicht jede Sprache verwendet alle sechs Kategorien. Englisch verwendet nur zwei: one und other. Die Kategorie one gilt für die Anzahl 1, und other gilt für alles andere.
Arabisch verwendet alle sechs Kategorien. Die Kategorie zero gilt für 0, one für 1, two für 2, few für Zahlen wie 3-10, many für Zahlen wie 11-99 und other für Zahlen wie 100 und höher.
Russisch verwendet drei Kategorien: one für Zahlen, die auf 1 enden (außer 11), few für Zahlen, die auf 2-4 enden (außer 12-14), und many für alles andere.
Japanisch und Chinesisch verwenden nur die Kategorie other, da diese Sprachen nicht zwischen Singular- und Pluralformen unterscheiden.
Diese Kategorien repräsentieren die linguistischen Regeln jeder Sprache. Wenn Sie Übersetzungen bereitstellen, erstellen Sie einen String für jede Kategorie, die die Sprache verwendet.
Abrufen von Pluralkategorien mit resolvedOptions
Die Methode resolvedOptions() einer PluralRules-Instanz gibt ein Objekt zurück, das Informationen über die Regeln enthält, einschließlich der Pluralkategorien, die die Locale verwendet.
const enRules = new Intl.PluralRules('en-US');
const options = enRules.resolvedOptions();
console.log(options.pluralCategories);
// Output: ["one", "other"]
Die Eigenschaft pluralCategories ist ein Array von Strings. Jeder String ist einer der sechs Standard-Kategorienamen. Das Array enthält nur die Kategorien, die die Locale tatsächlich verwendet.
Für Englisch enthält das Array one und other, da Englisch zwischen Singular- und Pluralformen unterscheidet.
Für eine Sprache mit komplexeren Regeln enthält das Array mehr Kategorien:
const arRules = new Intl.PluralRules('ar-EG');
const options = arRules.resolvedOptions();
console.log(options.pluralCategories);
// Output: ["zero", "one", "two", "few", "many", "other"]
Arabisch verwendet alle sechs Kategorien, daher enthält das Array alle sechs Werte.
Pluralkategorien für verschiedene Locales anzeigen
Verschiedene Sprachen haben unterschiedliche Pluralregeln, was bedeutet, dass sie unterschiedliche Kategorien verwenden. Vergleichen Sie mehrere Sprachen, um die Variation zu sehen:
const locales = ['en-US', 'ar-EG', 'ru-RU', 'pl-PL', 'ja-JP', 'zh-CN'];
locales.forEach(locale => {
const rules = new Intl.PluralRules(locale);
const categories = rules.resolvedOptions().pluralCategories;
console.log(`${locale}: [${categories.join(', ')}]`);
});
// Output:
// en-US: [one, other]
// ar-EG: [zero, one, two, few, many, other]
// ru-RU: [one, few, many, other]
// pl-PL: [one, few, many, other]
// ja-JP: [other]
// zh-CN: [other]
Englisch hat zwei Kategorien. Arabisch hat sechs. Russisch und Polnisch haben jeweils vier. Japanisch und Chinesisch haben nur eine, da sie keine Pluralformen unterscheiden.
Diese Variation zeigt, warum man nicht davon ausgehen kann, dass jede Sprache wie Englisch funktioniert. Sie müssen prüfen, welche Kategorien jede Locale verwendet und entsprechende Übersetzungen für jede bereitstellen.
Verstehen, was Kategorien für jede Locale bedeuten
Der gleiche Kategoriename bedeutet in verschiedenen Sprachen unterschiedliche Dinge. Die Kategorie "one" im Englischen gilt nur für die Zahl 1. Im Russischen gilt "one" für Zahlen, die auf 1 enden, außer 11, also für 1, 21, 31, 101 und so weiter.
Testen Sie, welche Zahlen in verschiedenen Locales zu welchen Kategorien gehören:
const enRules = new Intl.PluralRules('en-US');
const ruRules = new Intl.PluralRules('ru-RU');
const numbers = [0, 1, 2, 3, 5, 11, 21, 22, 100];
console.log('English:');
numbers.forEach(n => {
console.log(` ${n}: ${enRules.select(n)}`);
});
console.log('Russian:');
numbers.forEach(n => {
console.log(` ${n}: ${ruRules.select(n)}`);
});
// Output:
// English:
// 0: other
// 1: one
// 2: other
// 3: other
// 5: other
// 11: other
// 21: other
// 22: other
// 100: other
// Russian:
// 0: many
// 1: one
// 2: few
// 3: few
// 5: many
// 11: many
// 21: one
// 22: few
// 100: many
Im Englischen verwendet nur die 1 die Kategorie "one". Im Russischen verwenden 1 und 21 beide "one", weil sie auf 1 enden. Die Zahlen 2, 3 und 22 verwenden "few", weil sie auf 2-4 enden. Die Zahlen 0, 5, 11 und 100 verwenden "many".
Dies zeigt, dass man nicht vorhersagen kann, welche Kategorie auf eine Zahl zutrifft, ohne die Sprachregeln zu kennen. Das Array pluralCategories teilt Ihnen mit, welche Kategorien existieren, und die Methode select() gibt an, welche Kategorie auf jede Zahl zutrifft.
Kategorien für Ordnungszahlen abrufen
Ordnungszahlen wie 1., 2., 3. haben ihre eigenen Pluralregeln, die sich von Kardinalzahlen unterscheiden. Erstellen Sie eine PluralRules-Instanz mit type: 'ordinal', um die Kategorien für Ordnungszahlen zu erhalten:
const enCardinalRules = new Intl.PluralRules('en-US', { type: 'cardinal' });
const enOrdinalRules = new Intl.PluralRules('en-US', { type: 'ordinal' });
console.log('Cardinal:', enCardinalRules.resolvedOptions().pluralCategories);
// Output: Cardinal: ["one", "other"]
console.log('Ordinal:', enOrdinalRules.resolvedOptions().pluralCategories);
// Output: Ordinal: ["one", "two", "few", "other"]
Englische Kardinalzahlen verwenden zwei Kategorien. Englische Ordnungszahlen verwenden vier Kategorien, weil Ordnungszahlen zwischen 1st, 2nd, 3rd und allen anderen unterscheiden müssen.
Die Ordnungskategorien entsprechen den Ordnungssuffixen:
const enOrdinalRules = new Intl.PluralRules('en-US', { type: 'ordinal' });
const numbers = [1, 2, 3, 4, 11, 21, 22, 23];
numbers.forEach(n => {
const category = enOrdinalRules.select(n);
console.log(`${n}: ${category}`);
});
// Output:
// 1: one
// 2: two
// 3: few
// 4: other
// 11: other
// 21: one
// 22: two
// 23: few
Die Kategorie "one" entspricht dem Suffix "st" (1st, 21st), "two" entspricht "nd" (2nd, 22nd), "few" entspricht "rd" (3rd, 23rd) und "other" entspricht "th" (4th, 11th).
Verschiedene Sprachen haben unterschiedliche Ordnungskategorien:
const locales = ['en-US', 'es-ES', 'fr-FR'];
locales.forEach(locale => {
const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
const categories = rules.resolvedOptions().pluralCategories;
console.log(`${locale}: [${categories.join(', ')}]`);
});
// Output:
// en-US: [one, two, few, other]
// es-ES: [other]
// fr-FR: [one, other]
Spanisch verwendet nur eine Ordnungskategorie, da spanische Ordnungszahlen einem einfacheren Muster folgen. Französisch verwendet zwei Kategorien, um die erste Position von allen anderen Positionen zu unterscheiden.
Verwendung von Pluralkategorien zum Erstellen von Übersetzungszuordnungen
Wenn Sie wissen, welche Kategorien eine Locale verwendet, können Sie eine Übersetzungszuordnung mit genau der richtigen Anzahl von Einträgen erstellen:
function buildTranslationMap(locale, translations) {
const rules = new Intl.PluralRules(locale);
const categories = rules.resolvedOptions().pluralCategories;
const map = new Map();
categories.forEach(category => {
if (translations[category]) {
map.set(category, translations[category]);
} else {
console.warn(`Missing translation for category "${category}" in locale "${locale}"`);
}
});
return map;
}
const enTranslations = {
one: 'item',
other: 'items'
};
const arTranslations = {
zero: 'لا توجد عناصر',
one: 'عنصر واحد',
two: 'عنصران',
few: 'عناصر',
many: 'عنصرًا',
other: 'عنصر'
};
const enMap = buildTranslationMap('en-US', enTranslations);
const arMap = buildTranslationMap('ar-EG', arTranslations);
console.log(enMap);
// Output: Map(2) { 'one' => 'item', 'other' => 'items' }
console.log(arMap);
// Output: Map(6) { 'zero' => 'لا توجد عناصر', 'one' => 'عنصر واحد', ... }
Diese Funktion prüft, ob Sie Übersetzungen für alle erforderlichen Kategorien bereitgestellt haben und warnt Sie, wenn welche fehlen. Dies verhindert Laufzeitfehler, wenn eine Kategorie verwendet wird, aber keine Übersetzung vorhanden ist.
Validierung der Vollständigkeit von Übersetzungen
Verwenden Sie Pluralkategorien, um zu überprüfen, ob Ihre Übersetzungen alle notwendigen Formen enthalten, bevor Sie sie in die Produktion übernehmen:
function validateTranslations(locale, translations) {
const rules = new Intl.PluralRules(locale);
const requiredCategories = rules.resolvedOptions().pluralCategories;
const providedCategories = Object.keys(translations);
const missing = requiredCategories.filter(cat => !providedCategories.includes(cat));
const extra = providedCategories.filter(cat => !requiredCategories.includes(cat));
if (missing.length > 0) {
console.error(`Locale ${locale} is missing categories: ${missing.join(', ')}`);
return false;
}
if (extra.length > 0) {
console.warn(`Locale ${locale} has unused categories: ${extra.join(', ')}`);
}
return true;
}
const enTranslations = {
one: 'item',
other: 'items'
};
const incompleteArTranslations = {
one: 'عنصر واحد',
other: 'عنصر'
};
validateTranslations('en-US', enTranslations);
// Output: true
validateTranslations('ar-EG', incompleteArTranslations);
// Output: Locale ar-EG is missing categories: zero, two, few, many
// Output: false
Diese Validierung erkennt fehlende Übersetzungen während der Entwicklung, anstatt sie erst zu entdecken, wenn Benutzer auf nicht übersetzte Texte stoßen.
Dynamische Übersetzungsschnittstellen erstellen
Beim Erstellen von Tools für Übersetzer sollten die Pluralkategorien abgefragt werden, um genau anzuzeigen, welche Formen übersetzt werden müssen:
function generateTranslationForm(locale, key) {
const rules = new Intl.PluralRules(locale);
const categories = rules.resolvedOptions().pluralCategories;
const form = document.createElement('div');
form.className = 'translation-form';
const heading = document.createElement('h3');
heading.textContent = `Translate "${key}" for ${locale}`;
form.appendChild(heading);
categories.forEach(category => {
const label = document.createElement('label');
label.textContent = `${category}:`;
const input = document.createElement('input');
input.type = 'text';
input.name = `${key}.${category}`;
input.placeholder = `Enter ${category} form`;
const wrapper = document.createElement('div');
wrapper.appendChild(label);
wrapper.appendChild(input);
form.appendChild(wrapper);
});
return form;
}
const enForm = generateTranslationForm('en-US', 'items');
const arForm = generateTranslationForm('ar-EG', 'items');
document.body.appendChild(enForm);
document.body.appendChild(arForm);
Dies generiert ein Formular mit der korrekten Anzahl von Eingabefeldern für jede Locale. Englisch erhält zwei Felder (one und other), während Arabisch sechs Felder erhält (zero, one, two, few, many und other).
Kategorien über verschiedene Locales hinweg vergleichen
Bei der Verwaltung von Übersetzungen für mehrere Locales sollte man vergleichen, welche Kategorien sie verwenden, um die Komplexität der Übersetzung zu verstehen:
function compareLocalePluralCategories(locales) {
const comparison = {};
locales.forEach(locale => {
const rules = new Intl.PluralRules(locale);
const categories = rules.resolvedOptions().pluralCategories;
comparison[locale] = categories;
});
return comparison;
}
const locales = ['en-US', 'es-ES', 'ar-EG', 'ru-RU', 'ja-JP'];
const comparison = compareLocalePluralCategories(locales);
console.log(comparison);
// Output:
// {
// 'en-US': ['one', 'other'],
// 'es-ES': ['one', 'other'],
// 'ar-EG': ['zero', 'one', 'two', 'few', 'many', 'other'],
// 'ru-RU': ['one', 'few', 'many', 'other'],
// 'ja-JP': ['other']
// }
Dies zeigt, dass Englisch und Spanisch die gleichen Pluralkategorien haben, was es einfach macht, Übersetzungsstrukturen zwischen ihnen wiederzuverwenden. Arabisch erfordert deutlich mehr Übersetzungsarbeit, da es sechs Kategorien verwendet.
Überprüfen, ob eine Locale eine bestimmte Kategorie verwendet
Bevor Sie eine bestimmte Pluralkategorie in Ihrem Code verwenden, überprüfen Sie, ob die Locale diese tatsächlich nutzt:
function localeUsesCategory(locale, category) {
const rules = new Intl.PluralRules(locale);
const categories = rules.resolvedOptions().pluralCategories;
return categories.includes(category);
}
console.log(localeUsesCategory('en-US', 'zero'));
// Output: false
console.log(localeUsesCategory('ar-EG', 'zero'));
// Output: true
console.log(localeUsesCategory('ja-JP', 'one'));
// Output: false
Dies verhindert, dass Sie annehmen, jede Locale habe eine zero-Kategorie oder one-Kategorie. Verwenden Sie diese Überprüfung, um kategoriespezifische Logik sicher zu implementieren.
Die other-Kategorie verstehen
Jede Sprache verwendet die other-Kategorie. Diese Kategorie dient als Standardfall, wenn keine andere Kategorie zutrifft.
Im Englischen deckt other alle Zählwerte außer 1 ab. Im Arabischen deckt other große Zahlen wie 100 und höher ab. Im Japanischen deckt other alle Zählwerte ab, da Japanisch keine Pluralformen unterscheidet.
Stellen Sie immer eine Übersetzung für die other-Kategorie bereit. Diese Kategorie existiert garantiert in jeder Locale und wird verwendet, wenn keine spezifischere Kategorie übereinstimmt.
const locales = ['en-US', 'ar-EG', 'ru-RU', 'ja-JP'];
locales.forEach(locale => {
const rules = new Intl.PluralRules(locale);
const categories = rules.resolvedOptions().pluralCategories;
const hasOther = categories.includes('other');
console.log(`${locale} uses "other": ${hasOther}`);
});
// Output:
// en-US uses "other": true
// ar-EG uses "other": true
// ru-RU uses "other": true
// ja-JP uses "other": true
Alle aufgelösten Optionen zusammen erhalten
Die Methode resolvedOptions() gibt nicht nur Pluralkategorien zurück. Sie enthält Informationen über die Locale, den Typ und die Zahlenformatierungsoptionen:
const rules = new Intl.PluralRules('de-DE', {
type: 'cardinal',
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
const options = rules.resolvedOptions();
console.log(options);
// Output:
// {
// locale: 'de-DE',
// type: 'cardinal',
// pluralCategories: ['one', 'other'],
// minimumIntegerDigits: 1,
// minimumFractionDigits: 2,
// maximumFractionDigits: 2,
// minimumSignificantDigits: undefined,
// maximumSignificantDigits: undefined
// }
Die Eigenschaft pluralCategories ist ein Teil der Informationen im Objekt der aufgelösten Optionen. Die anderen Eigenschaften zeigen Ihnen die exakte Konfiguration, die die PluralRules-Instanz verwendet, einschließlich aller Optionen, die auf Standardwerte gesetzt wurden.
Caching von Pluralkategorien für bessere Performance
Das Erstellen von PluralRules-Instanzen und der Aufruf von resolvedOptions() verursacht Kosten. Speichern Sie die Ergebnisse für jede Locale im Cache, anstatt sie wiederholt abzufragen:
const categoriesCache = new Map();
function getPluralCategories(locale, type = 'cardinal') {
const key = `${locale}:${type}`;
if (categoriesCache.has(key)) {
return categoriesCache.get(key);
}
const rules = new Intl.PluralRules(locale, { type });
const categories = rules.resolvedOptions().pluralCategories;
categoriesCache.set(key, categories);
return categories;
}
const enCardinal = getPluralCategories('en-US', 'cardinal');
const enOrdinal = getPluralCategories('en-US', 'ordinal');
const arCardinal = getPluralCategories('ar-EG', 'cardinal');
console.log('en-US cardinal:', enCardinal);
console.log('en-US ordinal:', enOrdinal);
console.log('ar-EG cardinal:', arCardinal);
// Nachfolgende Aufrufe verwenden zwischengespeicherte Ergebnisse
const enCardinal2 = getPluralCategories('en-US', 'cardinal');
// Keine neue PluralRules-Instanz wird erstellt
Dieses Muster ist besonders wichtig in Anwendungen, die viele pluralisierte Strings formatieren oder viele Locales unterstützen.
Browser-Unterstützung und Kompatibilität
Die Eigenschaft pluralCategories bei resolvedOptions() wurde 2020 zu JavaScript hinzugefügt. Sie wird in Chrome 106+, Firefox 116+, Safari 15.4+ und Edge 106+ unterstützt.
Ältere Browser, die Intl.PluralRules unterstützen, aber nicht pluralCategories, geben undefined für diese Eigenschaft zurück. Überprüfen Sie die Existenz, bevor Sie sie verwenden:
function getPluralCategories(locale) {
const rules = new Intl.PluralRules(locale);
const options = rules.resolvedOptions();
if (options.pluralCategories) {
return options.pluralCategories;
}
// Fallback für ältere Browser
return ['one', 'other'];
}
Dieser Fallback nimmt ein einfaches Zwei-Kategorien-System an, das für Englisch und viele europäische Sprachen funktioniert, aber möglicherweise nicht für Sprachen mit komplexeren Regeln korrekt ist. Für bessere Kompatibilität sollten Sie sprachspezifische Fallbacks oder einen Polyfill verwenden.