CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-make-plural

Unicode CLDR pluralization rules as JavaScript functions for internationalization applications

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

example-values.mddocs/

Example Values

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.

Capabilities

Example Objects

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 Patterns

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";

Language Example Objects

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", ...]

Usage Examples

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 empty

Building 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'));

Example Value Formats

Number Representations:

  • "1" - Single number
  • "2~4" - Range (2, 3, 4)
  • "1.5" - Decimal number
  • "0.0~1.5" - Decimal range

Range 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)

Language-Specific Example Patterns

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)

JSON Data Access

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
);

Practical Applications

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.

docs

cardinal-pluralization.md

core-pluralization.md

example-values.md

index.md

ordinal-pluralization.md

plural-categories.md

range-pluralization.md

tile.json