功能说明
formatOrdinal 把整数转换为英语序数词形式,例如 1st、2nd、3rd、11th、21st,内部使用 Intl.PluralRules 的 ordinal 类型判断后缀,而不是对 10 取模的硬编码分支。formatOrdinalList 批量处理一组数字。适用于排行榜名次、步骤编号、周年纪念和表单中的第几项提示。
关键代码
PluralRules 会根据语言和数值返回 one、two、few、other 等序数类别,英语映射表把类别转换为 st、nd、rd、th。取绝对值后判断,避免负数出现 -1st 之类的异常组合。若语言不是英语,函数不再猜测后缀,而是退回普通数字格式化,保证输出至少是正确可读的数字。输入必须是整数,小数会被拒绝。
使用注意
英语序数规则对 11、12、13 特殊,PluralRules 已正确处理,不要自行用模十逻辑替换。其他语言可能需要本地化词缀或前置词,本函数只做数字回退,真正国际化应使用支持序数的本地化库或按语言分支。返回的是纯文本,不适合参与数值排序。负数的符号仍保留在数字前,阅读顺序需由界面保证。
验证方式
覆盖 1、2、3、4、11、12、13、21、22、23、101、111 等关键值,确认后缀符合英语规则。测试 0 与负数,确认不产生错误后缀。传入 zh-CN 或 fr 验证回退为普通数字,测试小数、NaN、字符串输入会抛错。批量函数再验证空数组、顺序保持与元素类型检查。
代码示例
const EN_ORDINAL_SUFFIX = { one: "st", two: "nd", few: "rd", other: "th" };
export function formatOrdinal(value, locale = "en") {
if (!Number.isInteger(value)) throw new TypeError("value must be an integer");
const rules = new Intl.PluralRules(locale, { type: "ordinal" });
const suffix = locale.toLowerCase().startsWith("en")
? EN_ORDINAL_SUFFIX[rules.select(Math.abs(value))]
: "";
return suffix
? String(value) + suffix
: new Intl.NumberFormat(locale).format(value);
}
export function formatOrdinalList(values, locale = "en") {
if (!Array.isArray(values)) throw new TypeError("values must be an array");
return values.map((value) => formatOrdinal(value, locale));
}