Unicode CLDR pluralization rules as JavaScript functions for internationalization applications
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Metadata about available plural categories for each language, including both cardinal and ordinal categories. This module provides the category information without the pluralization logic.
Each language provides an object with arrays of available categories for cardinal and ordinal pluralization.
/**
* Language category metadata
*/
interface LanguageCategories {
cardinal: PluralCategory[];
ordinal: PluralCategory[];
}
type PluralCategory = "zero" | "one" | "two" | "few" | "many" | "other";import * as Categories from "make-plural/pluralCategories";
// Or import specific languages
import { en, ar, fr } from "make-plural/pluralCategories";All 219 languages provide category metadata:
Examples by Complexity:
Simple Two-Category Languages:
Categories.en.cardinal // ["one", "other"]
Categories.de.cardinal // ["one", "other"]
Categories.nl.cardinal // ["one", "other"]
Categories.sv.cardinal // ["one", "other"]Three-Category Languages:
Categories.fr.cardinal // ["one", "many", "other"]
Categories.pt.cardinal // ["one", "many", "other"]
Categories.es.cardinal // ["one", "many", "other"]
Categories.it.cardinal // ["one", "many", "other"]Four-Category Languages:
Categories.pl.cardinal // ["one", "few", "many", "other"]
Categories.ru.cardinal // ["one", "few", "many", "other"]
Categories.uk.cardinal // ["one", "few", "many", "other"]
Categories.hr.cardinal // ["one", "few", "many", "other"]Complex Six-Category Languages:
Categories.ar.cardinal // ["zero", "one", "two", "few", "many", "other"]
Categories.cy.cardinal // ["zero", "one", "two", "few", "many", "other"]Single-Category Languages:
Categories.zh.cardinal // ["other"]
Categories.ja.cardinal // ["other"]
Categories.ko.cardinal // ["other"]
Categories.vi.cardinal // ["other"]Languages with ordinal rules (105 languages) provide ordinal category arrays:
English Ordinals:
Categories.en.cardinal // ["one", "other"]
Categories.en.ordinal // ["one", "two", "few", "other"]Welsh Complex Ordinals:
Categories.cy.cardinal // ["zero", "one", "two", "few", "many", "other"]
Categories.cy.ordinal // ["zero", "one", "two", "few", "many", "other"]French Simple Ordinals:
Categories.fr.cardinal // ["one", "many", "other"]
Categories.fr.ordinal // ["one", "other"]Languages Without Ordinal Rules:
Categories.zh.cardinal // ["other"]
Categories.zh.ordinal // ["other"]
Categories.ja.cardinal // ["other"]
Categories.ja.ordinal // ["other"]Checking Available Categories:
import * as Categories from "make-plural/pluralCategories";
// Check what categories a language supports
function getLanguageInfo(lang) {
const langCategories = Categories[lang];
return {
cardinalCount: langCategories.cardinal.length,
ordinalCount: langCategories.ordinal.length,
hasComplexCardinals: langCategories.cardinal.length > 2,
hasComplexOrdinals: langCategories.ordinal.length > 2,
categories: langCategories
};
}
console.log(getLanguageInfo('en'));
// {
// cardinalCount: 2,
// ordinalCount: 4,
// hasComplexCardinals: false,
// hasComplexOrdinals: true,
// categories: { cardinal: ["one", "other"], ordinal: ["one", "two", "few", "other"] }
// }
console.log(getLanguageInfo('ar'));
// {
// cardinalCount: 6,
// ordinalCount: 1,
// hasComplexCardinals: true,
// hasComplexOrdinals: false,
// categories: { cardinal: ["zero", "one", "two", "few", "many", "other"], ordinal: ["other"] }
// }Building Localization Systems:
import * as Categories from "make-plural/pluralCategories";
// Generate template objects for translations
function generateTranslationTemplate(languages) {
const template = {};
for (const lang of languages) {
template[lang] = {
cardinal: {},
ordinal: {}
};
// Create empty slots for each category
Categories[lang].cardinal.forEach(category => {
template[lang].cardinal[category] = "";
});
Categories[lang].ordinal.forEach(category => {
template[lang].ordinal[category] = "";
});
}
return template;
}
const template = generateTranslationTemplate(['en', 'fr', 'ar']);
console.log(template);
// {
// en: {
// cardinal: { one: "", other: "" },
// ordinal: { one: "", two: "", few: "", other: "" }
// },
// fr: {
// cardinal: { one: "", many: "", other: "" },
// ordinal: { one: "", other: "" }
// },
// ar: {
// cardinal: { zero: "", one: "", two: "", few: "", many: "", other: "" },
// ordinal: { other: "" }
// }
// }Validation and Analysis:
import * as Categories from "make-plural/pluralCategories";
// Analyze language complexity
function analyzeLanguageComplexity() {
const analysis = {
simple: [], // 1-2 categories
moderate: [], // 3-4 categories
complex: [] // 5-6 categories
};
for (const [lang, categories] of Object.entries(Categories)) {
const cardinalCount = categories.cardinal.length;
if (cardinalCount <= 2) {
analysis.simple.push(lang);
} else if (cardinalCount <= 4) {
analysis.moderate.push(lang);
} else {
analysis.complex.push(lang);
}
}
return analysis;
}
// Find languages with ordinal rules
function getOrdinalLanguages() {
return Object.entries(Categories)
.filter(([lang, categories]) =>
categories.ordinal.length > 1 ||
(categories.ordinal.length === 1 && categories.ordinal[0] !== "other")
)
.map(([lang]) => lang);
}
console.log(getOrdinalLanguages().length); // 105Form Generation:
import * as Categories from "make-plural/pluralCategories";
// Generate form fields for translation interface
function generatePluralForm(language, type = 'cardinal') {
const categories = Categories[language][type];
return categories.map(category => ({
field: `${language}_${type}_${category}`,
label: `${language} ${type} ${category}`,
placeholder: `Enter ${category} form...`
}));
}Validation:
import * as Categories from "make-plural/pluralCategories";
// Validate translation completeness
function validateTranslations(translations, language) {
const required = Categories[language];
const errors = [];
// Check cardinal categories
required.cardinal.forEach(category => {
if (!translations[language]?.cardinal?.[category]) {
errors.push(`Missing cardinal ${category} for ${language}`);
}
});
// Check ordinal categories
required.ordinal.forEach(category => {
if (!translations[language]?.ordinal?.[category]) {
errors.push(`Missing ordinal ${category} for ${language}`);
}
});
return errors;
}By Cardinal Category Count:
Ordinal Complexity: