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
Sample numeric values that demonstrate each plural category for every supported language. This module provides concrete examples to understand how pluralization rules work in practice.
Each language provides sample numbers that fall into each plural category for both cardinal and ordinal pluralization.
/**
* Language example values
*/
interface LanguageExamples {
cardinal: Record<PluralCategory, string[]>;
ordinal: Record<PluralCategory, string[]>;
}
type PluralCategory = "zero" | "one" | "two" | "few" | "many" | "other";import * as Examples from "make-plural/examples";
// Or import specific languages
import { en, ar, fr } from "make-plural/examples";
// Or import raw JSON data
import ExamplesJSON from "make-plural/examples.json";All 219 languages provide example values:
English Examples:
Examples.en.cardinal.one // ["1"]
Examples.en.cardinal.other // ["0", "2~16", "100", "1000", "10000", "100000", "1000000", ...]
Examples.en.ordinal.one // ["1", "21", "31", "41", "51", "61", "71", "81", "91", ...]
Examples.en.ordinal.two // ["2", "22", "32", "42", "52", "62", "72", "82", "92", ...]
Examples.en.ordinal.few // ["3", "23", "33", "43", "53", "63", "73", "83", "93", ...]
Examples.en.ordinal.other // ["0", "4~18", "100", "1000", "10000", "100000", "1000000", ...]Arabic Examples (Complex 6-Category System):
Examples.ar.cardinal.zero // ["0"]
Examples.ar.cardinal.one // ["1"]
Examples.ar.cardinal.two // ["2"]
Examples.ar.cardinal.few // ["3~10", "103~110", "1003", ...]
Examples.ar.cardinal.many // ["11~26", "111", "1011", ...]
Examples.ar.cardinal.other // ["100~102", "200~202", "300~302", ...]
Examples.ar.ordinal.other // ["0~15", "100", "1000", "10000", ...]Polish Examples (4-Category System):
Examples.pl.cardinal.one // ["1"]
Examples.pl.cardinal.few // ["2~4", "22~24", "32~34", ...]
Examples.pl.cardinal.many // ["0", "5~19", "100", "1000", ...]
Examples.pl.cardinal.other // ["0.0~1.5", "10.0", "100.0", ...]
Examples.pl.ordinal.other // ["0~15", "100", "1000", "10000", ...]Chinese Examples (Single Category):
Examples.zh.cardinal.other // ["0~15", "100", "1000", "10000", ...]
Examples.zh.ordinal.other // ["0~15", "100", "1000", "10000", ...]Understanding Pluralization Rules:
import * as Examples from "make-plural/examples";
import { en, ar, pl } from "make-plural";
// Test English examples
Examples.en.cardinal.one.forEach(num => {
console.log(`${num}: ${en(parseFloat(num))}`);
});
// 1: one
Examples.en.ordinal.two.forEach(num => {
console.log(`${num}: ${en(parseFloat(num), true)}`);
});
// 2: two, 22: two, 32: two, etc.
// Test Arabic examples
Examples.ar.cardinal.few.forEach(num => {
if (!num.includes('~')) { // Skip ranges for clarity
console.log(`${num}: ${ar(parseFloat(num))}`);
}
});
// 3: few, 4: few, 5: few, etc.Testing Pluralization Functions:
import * as Examples from "make-plural/examples";
import { en, fr, ar } from "make-plural";
// Validate that examples match expected categories
function validateExamples(lang, pluralFn, examples) {
const errors = [];
for (const [expectedCategory, exampleValues] of Object.entries(examples.cardinal)) {
for (const value of exampleValues) {
if (value.includes('~')) continue; // Skip ranges
const actualCategory = pluralFn(parseFloat(value));
if (actualCategory !== expectedCategory) {
errors.push(`${lang}: ${value} expected ${expectedCategory}, got ${actualCategory}`);
}
}
}
return errors;
}
// Test English
const enErrors = validateExamples('en', en, Examples.en);
console.log(enErrors); // Should be empty
// Test French
const frErrors = validateExamples('fr', fr, Examples.fr);
console.log(frErrors); // Should be emptyBuilding Test Suites:
import * as Examples from "make-plural/examples";
// Generate comprehensive test cases
function generatePluralTests(languages) {
const tests = [];
for (const lang of languages) {
const examples = Examples[lang];
// Test cardinal examples
for (const [category, values] of Object.entries(examples.cardinal)) {
for (const value of values) {
if (!value.includes('~')) { // Skip ranges
tests.push({
language: lang,
value: parseFloat(value),
type: 'cardinal',
expected: category
});
}
}
}
// Test ordinal examples
for (const [category, values] of Object.entries(examples.ordinal)) {
for (const value of values) {
if (!value.includes('~')) { // Skip ranges
tests.push({
language: lang,
value: parseFloat(value),
type: 'ordinal',
expected: category
});
}
}
}
}
return tests;
}Documentation Generation:
import * as Examples from "make-plural/examples";
// Generate human-readable documentation
function generatePluralDocs(language) {
const examples = Examples[language];
let docs = `# ${language.toUpperCase()} Pluralization Examples\n\n`;
docs += `## Cardinal Numbers\n\n`;
for (const [category, values] of Object.entries(examples.cardinal)) {
docs += `**${category}**: ${values.slice(0, 5).join(', ')}${values.length > 5 ? ', ...' : ''}\n\n`;
}
docs += `## Ordinal Numbers\n\n`;
for (const [category, values] of Object.entries(examples.ordinal)) {
docs += `**${category}**: ${values.slice(0, 5).join(', ')}${values.length > 5 ? ', ...' : ''}\n\n`;
}
return docs;
}
console.log(generatePluralDocs('en'));Number Representations:
"1" - Single number"2~4" - Range (2, 3, 4)"1.5" - Decimal number"0.0~1.5" - Decimal rangeRange Interpretation:
// "2~4" represents the values: 2, 3, 4
// "103~110" represents: 103, 104, 105, 106, 107, 108, 109, 110
// "0.0~1.5" represents decimal values from 0.0 to 1.5 (typically step by 0.1)English Cardinal Patterns:
one: Just [1]other: Everything else [0, 2-16, 100, 1000, ...]English Ordinal Patterns:
one: [1, 21, 31, 41, 51, 61, 71, 81, 91, 101, 121, ...]two: [2, 22, 32, 42, 52, 62, 72, 82, 92, 102, 122, ...]few: [3, 23, 33, 43, 53, 63, 73, 83, 93, 103, 123, ...]other: [0, 4-20, 24-30, 34-40, ...]Arabic Cardinal Patterns:
zero: [0]one: [1]two: [2]few: [3-10, 103-110, 1003, ...]many: [11-26, 111, 1011, ...]other: [100-102, 200-202, 300-302, ...]Polish Cardinal Patterns:
one: [1]few: [2-4, 22-24, 32-34, 42-44, ...]many: [0, 5-21, 25-31, 35-41, 100, 1000, ...]other: [0.0-1.5, 10.0, 100.0, ...] (decimals)For applications needing raw data access:
import ExamplesJSON from "make-plural/examples.json";
// Direct JSON access (same structure as Examples module)
console.log(ExamplesJSON.en.cardinal.one); // ["1"]
console.log(ExamplesJSON.ar.cardinal.few); // ["3~10", "103~110", ...]
// Useful for server-side processing or data analysis
const allLanguages = Object.keys(ExamplesJSON);
const complexLanguages = allLanguages.filter(lang =>
Object.keys(ExamplesJSON[lang].cardinal).length > 3
);Interactive Documentation: Use examples to create interactive pluralization demos where users can see how different numbers are categorized.
Test Data Generation: Use examples as the basis for comprehensive test suites to validate pluralization implementations.
Rule Understanding: Help developers understand complex pluralization rules by seeing concrete examples of each category.
Translation Validation: Validate that translations cover all necessary plural forms by checking against example values.