npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

cldr-plural-rules

v1.0.0

Published

CLDR plural rules parser and evaluator.

Downloads

84

Readme

CLDR Plural Rules Parser

Parse and evaluate CLDR plural rules. Does not come with built-in plural rules; use Intl.PluralRules for that.

Usage

import { parseRuleSet, getPluralCategory } from 'cldr-plural-rules';

// Parse a plural rule set:
const rules = parseRuleSet(`
  one: n mod 10 = 1 and n != 11;
  few: n mod 100 = 2..4
`);

// Look up the plural category of a number:
console.log(getPluralCategory(rules, 0)); // other
console.log(getPluralCategory(rules, 1)); // one
console.log(getPluralCategory(rules, 4)); // few
console.log(getPluralCategory(rules, 11)); // other
console.log(getPluralCategory(rules, 42)); // other
console.log(getPluralCategory(rules, 103)); // few

About

In English, plurals are pretty straightforward. Nouns are singular if the number is 1, plural otherwise: 0 things, 1 thing, 2 things, 3 things, and so on. In French, singular is used for 0 as well: 0 truc, 1 truc, 2 trucs. Other languages go beyond mere singular vs plural, up to six distinct forms for Arabic. The rules can get pretty complex.

The CLDR defines a small grammar for plural rules. This package parses rule definitions into a high-level syntax tree, and can evaluate such a syntax tree to find a number's plural category. See the CLDR for details on the plural rule syntax.

This package can parse rule sets with multiple categories, as in the example under Usage. It can also parse a single category rule, as in n mod 10 = 1. The parser is strict and will throw an error if it encounters invalid syntax.

This package accepts plural categories of any name (that contains letters a-z), in addition to the standard categories zero, one, two, few, many and other. The other category is the fallback category used when no other matches; it cannot have any rules.

Sample values can be embedded alongside the rule. Sample values are retained but not verified by this package. They can be accessed through rule.samples (or ruleset.other for other category samples), which is null if no samples were specified.

Limitations

This is not a replacement for Intl.PluralRules. This package does not ship with any plural rules for any locales. It's strictly a parser and evaluator.

Rules are not validated for correctness. By CLDR's specification, rules must be non-overlapping. A rule set like one: n = 1; few: n mod 10 = 1 is invalid, as the number 1 matches both one and few. This package does not attempt to find overlapping categories; it just returns the first category that matches. Similarly, impossible rules like n = 0 and n = 1 or n in 10..1 are not detected.

Compatibility

The code makes use of ES6 classes, for...of and map @@iterator. It will run in evergreen browsers, but not IE11 or earlier. It also works in nearly all versions of Node.js (but only v14 and above are officially supported).

API documentation

parseRuleSet()

function parseRuleSet(source: string): PluralRuleSet

Parses a plural rule set, which contains plural categories, their corresponding conditions, and optional sample values for each category.

If sample values are included, the parser does not verify them.

Example:

one: n = 1;
two: n mod 10 = 2 and n != 12 @integer 2, 22, 32, 102, 112, 122, ...

The exact details of the syntax are described in the CLDR plural rules documentation.

Arguments:

  • source: The rule text to parse.

Returns: A high-level syntax tree containing the parsed rules. The returned value can be passed to getPluralCategory().

An individual category's rule can be accessed through ruleSet.rules.get('name').

parseRule()

function parseRule(source: string): PluralRule

Parses a single plural rule (without plural category name). The rule contains the conditions that trigger the rule, as well as optional sample values that the rule matches.

If sample values are included, the parser does not verify them.

Examples:

  • n = 1
  • n = 0, 1 or n in 11..19
  • n mod 10 not in 0, 4..8 @integer 1, 2, 3, 9, 11, 12, 13, 19, ...

Arguments:

  • source: The rule text to parse.

Returns: A high-level syntax tree containing the parsed rule. The returned value can be passed to testPluralRule().

getPluralCategory()

function getPluralCategory(rules: PluralRuleSet, n: number | string): string

Gets the plural category of a number based on the specified rules.

Arguments:

  • rules: The rule set to match the number against.
  • n: The number to get the plural category for. If the value is a string, it's parsed by parseFloat(). Decimal digits and exponents are taken from the input string. If the value is a number, decimal digits and exponents are taken from the String()-formatted value.

Returns: The first matching plural category, or 'other' if no category matched.

testPluralRule()

function testPluralRule(rule: PluralRule, n: number | string): boolean

Tests a single plural rule against a number.

Arguments:

  • rule: The rule to test the number against.
  • n: The number to test. If the value is a string, it's parsed by parseFloat(). Decimal digits and exponents are taken from the input string. If the value is a number, decimal digits and exponents are taken from the String()-formatted value.

Returns: True if the number matches the rule. Otherwise, false.

ParseError

class ParseError extends Error

The error type that is thrown when the parser encounters invalid syntax.

Changelog

v1.0.0 - 2023-06-26

Hello, 1.0!

Breaking changes:

  • Remove UMD bundles and associated sourcemaps.

Other changes:

  • Clarify earlier in README that this package does not supply any plural rules.