Guide to Intl.PluralRules in JavaScript
The Intl.PluralRules object is a native JavaScript API
designed to handle language-sensitive pluralization by determining the
correct grammatical plural category for any given number and locale.
While many developers assume pluralization is as simple as
distinguishing between singular (1) and plural (not 1), different
languages use complex grammatical rules involving dual forms, paucal
forms, and specific fractional behavior. This article explains how
Intl.PluralRules works, how it resolves locale-specific
plural categories, and how to implement it effectively in modern
applications.
What is
Intl.PluralRules?
Part of the ECMAScript Internationalization API (ECMA-402),
Intl.PluralRules does not format text or output translated
strings directly. Instead, it acts as a decision engine. When provided a
number and a locale, it returns one of the standard Unicode Common
Locale Data Repository (CLDR) plural categories:
zeroonetwofewmanyother
Every language supported by the runtime maps numbers to a subset of
these categories based on its linguistic rules. In all languages, the
other category serves as the mandatory fallback.
Basic Syntax
To create a plural rule matcher, instantiate the object with an optional locale and options object:
const pluralRules = new Intl.PluralRules(locales, options);locales(optional): A string or array of BCP 47 language tags (e.g.,'en-US','ar-EG','pl').options(optional): An object configuring rule selection:type: Either'cardinal'(default, for counting items) or'ordinal'(for ordering, such as 1st, 2nd, 3rd).minimumIntegerDigits,minimumFractionDigits,maximumFractionDigits, etc.: Formatting options that affect how fractions are categorized.
Cardinal Pluralization
Cardinal numbers represent quantities (e.g., 0 cars, 1 car, 5 cars).
In English, cardinal numbers only distinguish between
one and other:
const enRules = new Intl.PluralRules('en-US');
console.log(enRules.select(0)); // "other"
console.log(enRules.select(1)); // "one"
console.log(enRules.select(2)); // "other"
console.log(enRules.select(5)); // "other"Languages with richer plural systems require more categories. For example, Arabic utilizes all six plural forms:
const arRules = new Intl.PluralRules('ar-EG');
console.log(arRules.select(0)); // "zero"
console.log(arRules.select(1)); // "one"
console.log(arRules.select(2)); // "two"
console.log(arRules.select(3)); // "few" (numbers 3-10)
console.log(arRules.select(11)); // "many" (numbers 11-99)
console.log(arRules.select(100)); // "other"Ordinal Pluralization
Ordinal numbers indicate sequence or rank (e.g., 1st, 2nd, 3rd). By
setting the type option to 'ordinal',
Intl.PluralRules returns the rule category applicable to
positions:
const enOrdinalRules = new Intl.PluralRules('en-US', { type: 'ordinal' });
console.log(enOrdinalRules.select(1)); // "one" -> 1st
console.log(enOrdinalRules.select(2)); // "two" -> 2nd
console.log(enOrdinalRules.select(3)); // "few" -> 3rd
console.log(enOrdinalRules.select(4)); // "other" -> 4th
console.log(enOrdinalRules.select(21)); // "one" -> 21st
console.log(enOrdinalRules.select(22)); // "two" -> 22ndPractical Implementation: Building a Pluralization Function
Because Intl.PluralRules only returns category strings,
you use those categories to look up matching localized strings.
Example: Cardinal Messages
function formatItems(count, locale = 'en-US') {
const rules = new Intl.PluralRules(locale);
const rule = rules.select(count);
const messages = {
'en-US': {
one: `${count} item selected`,
other: `${count} items selected`
},
'ru': {
one: `${count} элемент выбран`,
few: `${count} элемента выбрано`,
many: `${count} элементов выбрано`,
other: `${count} элементов выбрано`
}
};
const localeMessages = messages[locale] || messages['en-US'];
return localeMessages[rule] || localeMessages['other'];
}
console.log(formatItems(1, 'en-US')); // "1 item selected"
console.log(formatItems(5, 'en-US')); // "5 items selected"
console.log(formatItems(1, 'ru')); // "1 элемент выбран"
console.log(formatItems(2, 'ru')); // "2 элемента выбрано"
console.log(formatItems(5, 'ru')); // "5 элементов выбрано"Example: Ordinal Suffixes
function getOrdinalSuffix(number, locale = 'en-US') {
const rules = new Intl.PluralRules(locale, { type: 'ordinal' });
const rule = rules.select(number);
const suffixes = {
one: 'st',
two: 'nd',
few: 'rd',
other: 'th'
};
return `${number}${suffixes[rule] || suffixes.other}`;
}
console.log(getOrdinalSuffix(1)); // "1st"
console.log(getOrdinalSuffix(2)); // "2nd"
console.log(getOrdinalSuffix(3)); // "3rd"
console.log(getOrdinalSuffix(11)); // "11th"
console.log(getOrdinalSuffix(21)); // "21st"Determining Supported Categories
To inspect which plural categories a particular locale supports
without guessing, use the resolvedOptions() method:
const rules = new Intl.PluralRules('ru');
console.log(rules.resolvedOptions().pluralCategories);
// Output: ["one", "few", "many", "other"]Summary
Intl.PluralRules removes the burden of writing custom,
fragile condition trees for plural strings across languages. By
offloading linguistic logic directly to the browser or runtime,
applications can achieve full internationalization compliance with
minimal code.