intl.pluralrules 是用于根据数字和语言返回标准复数类别的 api,如 "one"、"other",它不翻译也不拼接字符串,需配合本地化文案表实现 i18n 数量词适配。

Intl.PluralRules 是什么,它和 i18n 的数量词有什么关系
Intl.PluralRules 不是翻译工具,也不生成字符串,它只做一件事:给定一个数字和语言,返回对应的复数类别(如 "one"、"other")。英语里 1 是 "one",其余基本是 "other";阿拉伯语有 "zero"、"one"、"two"、"few"、"many"、"other" 六种;波兰语中 1 是 "one",2–4 是 "few",5+ 又回到 "other"。你得自己按这个分类去查表或拼接字符串。
怎么用 Intl.PluralRules 判断 1 还是 items
先创建规则实例,再调用 select() 方法:
const pr = new Intl.PluralRules("en-US");
console.log(pr.select(1)); // → "one"
console.log(pr.select(2)); // → "other"
console.log(pr.select(0)); // → "other"(英语里 0 也归 other)
关键点:
-
Intl.PluralRules构造时传入的 locale 必须是有效且受支持的语言标签(如"zh-CN"、"fr-FR"),不能是"zh"或"fr"这类简写——部分浏览器会 fallback,但行为不一致 - 返回值永远是字符串字面量:
"zero"、"one"、"two"、"few"、"many"、"other",没有"singular"或"plural"这种泛化名称 - 不要对返回值做字符串匹配以外的逻辑判断(比如
if (res === "one")安全,但if (res.includes("one"))会出错)
配合 lookup 表实现多语言 item/items 显示
你得自己维护一个映射表,按 Intl.PluralRules.select(n) 的结果取对应文案:
const messages = {
"en-US": { one: "1 item", other: "{n} items" },
"zh-CN": { other: "{n} 个商品" }, // 中文无单复数变化,统一用 other
"pl-PL": { one: "1 przedmiot", few: "{n} przedmioty", other: "{n} przedmiotów" }
};
function formatItem(n, locale = "en-US") {
const pr = new Intl.PluralRules(locale);
const category = pr.select(n);
const msg = messages[locale]?.[category] || messages["en-US"].other;
return msg.replace("{n}", String(n));
}
formatItem(1, "en-US"); // "1 item"
formatItem(2, "en-US"); // "2 items"
formatItem(2, "pl-PL"); // "2 przedmioty"
注意:
- 中文、日语、泰语等语言没有语法复数,
Intl.PluralRules对它们总是返回"other"(极少数方言例外),别强行拆分"one"/"other" - 不要在循环里反复 new
Intl.PluralRules——它可被复用,建议按 locale 缓存实例 -
formatItem(0, "en-US")返回"0 items",但业务上可能需要特殊处理(如显示 “No items”),这得在 lookup 表或调用前单独判断
常见错误:为什么 select(1) 有时返回 "other"
最常踩的坑是 locale 不匹配或未标准化:
- 传了
"en"而非"en-US":某些环境(如旧版 Safari)可能不识别简写,fallback 成默认 locale,而默认 locale 的复数规则未必是你想要的 - 用户语言是
"pt",但你只提供了"pt-BR"的文案表,Intl.PluralRules("pt")可能返回"one",但你的表里没这个 key,结果 fallback 出错 - 数字类型问题:
pr.select("1")会隐式转成 number,但pr.select(NaN)或pr.select(undefined)返回"other",且不报错——务必确保输入是有效数字
真正麻烦的不是 API 本身,而是每种语言的复数逻辑差异太大,而 Intl.PluralRules 只告诉你“属于哪一类”,不告诉你“这一类对应什么语义”。你得查 CLDR 数据、测试真实用户输入、并为每个 locale 单独配置文案映射。漏掉一种 category,就可能在波兰语里把 2 显示成错误格位。










