intl.pluralrules 是原生复数规则判断 api,根据语言和数字返回复数类别(如 "one"、"other"),i18n 框架依赖它实现多语言复数逻辑,但需手动映射类别到文案。

Intl.PluralRules 是什么,它和 i18n 的复数逻辑有什么关系
Intl.PluralRules 是浏览器和 Node.js(v12+)原生支持的 API,用于根据指定语言和数字,返回该数字在该语言中所属的复数类别(如 "one"、"other"、"few" 等)。它不生成文本,只做分类判断——这点常被误认为“能直接翻译”,结果卡在“为什么没输出文字”。
i18n 框架(比如 i18next、formatjs)内部依赖类似逻辑处理复数;但若你用的是轻量方案、或需手写提示文案(如表单校验、计数器旁的“1 个文件”/“3 个文件”),Intl.PluralRules 就是底层最干净的判断依据。
常见错误现象:new Intl.PluralRules("zh").select(2) 返回 "other",但你预期中文只有“单/复”两态,误以为 API 不准——其实中文确实只有 "other"(无语法性单复数区分),而阿拉伯语可能返回 "zero"、"one"、"two"、"few"、"many"、"other" 六类。
如何正确初始化并调用 select() 判断复数类别
关键在于:语言标签必须合法,且要考虑用户实际语言环境(不是硬写 "en" 就完事)。
实操建议:
- 优先用
navigator.language或服务端透传的accept-language值,避免降级到"en"导致规则错配 - 显式指定
type: "cardinal"(默认值,用于计数);若处理序数(如“第1名”“第2名”),才用type: "ordinal" - 构造实例时捕获异常:某些低版本安卓 WebView 不支持非
"en"locale,可 fallback 到new Intl.PluralRules("en") -
select()只接受数字(number类型),传字符串(如"2")会静默转为NaN,返回"other"—— 务必先Number(count)
示例:
const pr = new Intl.PluralRules(navigator.language || "en", { type: "cardinal" });
const category = pr.select(2); // 如 en-US → "other", ar → "few", ja → "other"
怎么把 category 映射成真正可用的文案
Intl.PluralRules 不提供文案,你得自己维护一个映射表。这个表必须按语言拆分,不能“一套文案走天下”。
使用场景决定结构粒度:
- 简单提示(如“删除 1 项?”):通常只需
"one"和"other"两档,中文、英文、日文都够用 - 面向中东或斯拉夫语系用户(如波兰语
"pl"):必须覆盖"one"、"few"、"many"、"other",否则 “2 个” 和 “5 个” 显示同一文案,违反本地化规范 - 避免用
switch硬编码所有语言:建议用对象字面量按locale分组,再查 category
示例(精简版):
const messages = {
"en": { one: "1 file", other: "{count} files" },
"zh": { other: "{count} 个文件" }, // 中文无 one 分支
"pl": { one: "1 plik", few: "{count} pliki", many: "{count} plików", other: "{count} pliku" }
};
const pr = new Intl.PluralRules(locale);
const category = pr.select(count);
return messages[locale]?.[category]?.replace("{count}", count) ?? messages["en"].other.replace("{count}", count);
容易被忽略的边界情况和性能注意点 复数逻辑看似简单,但真实项目里几个坑反复出现:
常见错误现象:在 React 组件里每次渲染都新建 Intl.PluralRules 实例,导致性能下降(尤其列表项多时);或未处理 count === 0 在部分语言中属于 "zero" 类别(如 "ar"、"fr"),但你的文案映射里没定义 "zero" 字段,结果 fallback 到 undefined。
实操建议:
- 缓存
Intl.PluralRules实例:按locale + type作为 key 存在 Map 或对象里,避免重复构造 - 对
count做防御性检查:小于 0 时多数语言归为"other",但业务上一般不显示负数,应提前拦截 - 服务端渲染(SSR)时,
navigator不存在,必须由请求头或配置传入locale,否则初始化失败 - Node.js 环境需确认 ICU 数据完整:Ubuntu 默认安装的 Node 可能缺多语言规则,
new Intl.PluralRules("ru")报RangeError,可用full-icu包修复










