Ever struggled with sorting words in different languages, handling tricky pluralization rules, or formatting lists in a way that sounds natural? The final parts of the Intl
API has some hidden gems that focuses on handling strings and lists.
TLDR
We will be focusing on three powerful but often overlooked features:
Intl.Collator
for sorting and comparing strings correctly.
Intl.PluralRules
for handling pluralization dynamically.
Intl.ListFormat
to format lists naturally and conjugation.
Intl.Collator
Sorting strings isn’t as straightforward as it seems. Different languages have different rules for alphabetical order, case sensitivity, and accents. That’s where Intl.Collator
comes in!
Basic Sorting
const collator = new Intl.Collator("en", { sensitivity: "base" });
console.log(collator.compare("apple", "Banana")); // -1 (apple comes before Banana)
console.log(collator.compare("banana", "apple")); // 1 (banana comes after apple)
console.log(collator.compare("apple", "apple")); // 0 (they are equal)
Here, { sensitivity: 'base' }
makes the comparison case-insensitive, so "apple" and "Apple" are treated the same.
Sorting an Array with Intl.Collator
const fruits = ["grape", "Banana", "apple", "Mango"];
fruits.sort(new Intl.Collator("en").compare);
console.log(fruits); // ['apple', 'Banana', 'grape', 'Mango']
Passing collator.compare
to .sort()
ensures correct ordering based on the locale.
String.localeCompare
vs Intl.Collator
Both of them can be used to sort but there are some important difference
-
Intl
by default supports localisation whilelocaleCompare
uses system or default locale has has limited customisation -
localeCompare
is easier or more straightforward to use'apple'.localeCompare('banana')
-
Intl.Collator
is faster -
Intl.Collator
supports multi-language sorting
Options
-
localeMatcher
: algorithm to use when comparing strings,'best fit'
(default) or'lookup'
, controls how locale is determined -
usage
: how the strings are compared,'sort'
(default) for sorting,'search'
for matching text -
sensitivity
: things to consider when comparing,'base'
,'accent'
,'case'
,'variant'
(most strict) -
ignorePunctuation
:true
ignores punctuation when comparing
Intl.PluralRules
: Smart Pluralization
Handling plurals correctly is trickier than just adding an "s." Different languages have complex rules for singular, dual, paucal, and plural forms. Intl.PluralRules
helps us determine the right plural form dynamically.
Basic Usage
const pluralRules = new Intl.PluralRules("en");
console.log(pluralRules.select(1)); // "one"
console.log(pluralRules.select(2)); // "other"
console.log(pluralRules.select(0)); // "other"
For English, "one"
is used for 1
, and "other"
is used for everything else.
Different Languages, Different Rules
For example, French considers 0
singular, while English treats it as plural.
const pluralRulesFr = new Intl.PluralRules("fr");
console.log(pluralRulesFr.select(1)); // "one"
console.log(pluralRulesFr.select(0)); // "one" (French treats 0 as singular!)
console.log(pluralRulesFr.select(2)); // "other"
Making Plural Messages Dynamic
function getItemMessage(count) {
const pluralRule = new Intl.PluralRules("en").select(count);
const messages = {
one: `You have ${count} message.`,
other: `You have ${count} messages.`,
};
return messages[pluralRule];
}
console.log(getItemMessage(1)); // "You have 1 message."
console.log(getItemMessage(3)); // "You have 3 messages."
This technique allows your app to automatically use the correct plural form.
Options
localeMatcher
-
type
:'cardinal'
(default) for counting objects,'ordinal'
for rankings (1st
,2nd
, etc.)
Option | Description |
---|---|
type |
'cardinal' (default) for counting objects, 'ordinal' for rankings (1st , 2nd , etc.) |
localeMatcher |
'best fit' or 'lookup' , controls locale selection |
Let’s see some examples with ordinal numbers:
const ordinalRules = new Intl.PluralRules("en", { type: "ordinal" });
console.log(ordinalRules.select(1)); // "one" (1st)
console.log(ordinalRules.select(2)); // "two" (2nd)
console.log(ordinalRules.select(3)); // "few" (3rd)
console.log(ordinalRules.select(4)); // "other" (4th, 5th, etc.)
Intl.ListFormat
: Formatting Lists Naturally
Writing a list of items (e.g., "apples, bananas, and oranges"
) is different across languages. Some use commas, others use "and" or "et," and some don't use conjunctions at all. Intl.ListFormat
makes it easy to format lists properly!
Basic Usage
const listFormatter = new Intl.ListFormat("en", {
style: "long",
type: "conjunction",
});
console.log(listFormatter.format(["apple", "banana", "cherry"]));
// "apple, banana, and cherry"
It automatically adds "and"
in the right place!
Different Locales and Styles
const listFormatterFr = new Intl.ListFormat("fr", {
style: "long",
type: "conjunction",
});
console.log(listFormatterFr.format(["pomme", "banane", "cerise"]));
// "pomme, banane et cerise" (French uses "et" instead of "and")
const shortFormatter = new Intl.ListFormat("en", {
style: "short",
type: "disjunction",
});
console.log(shortFormatter.format(["tea", "coffee", "milk"]));
// "tea, coffee, or milk" (disjunction uses "or" instead of "and")
Options
-
type
:'conjunction'
("and"
),'disjunction'
("or"
), or'unit'
(e.g.,"5 hours, 30 minutes"
) -
style
:'long'
(default, full words),'short'
(abbreviated),'narrow'
(minimal formatting)
Conclusion
That's how Intl.Collator
, Intl.PluralRules
, and Intl.ListFormat
can help make your JavaScript applications more international-friendly and user-friendly!
These APIs can save you a ton of work and help your app support multiple languages effortlessly.
Have you tried these Intl
features before?
Top comments (0)