先记住这个答案
把几个项目连成一句话,看起来 items.join('、') 就够了,但不同语言的规则差很多:中文是「A、B和C」,最后一项前用「和」不用顿号;美式英文是「A, B, and C」,最后一项前有逗号;英式英文和德语没有这个逗号。Intl.ListFormat 按语言数据处理这些细节,用法是 new Intl.ListFormat(locale, { type }).format(items)。type 默认是 conjunction,表示「和」;disjunction 表示「或」;unit 用来组合「5 英尺 7 英寸」这种单位。
format()接收字符串数组,返回按语言连好的一句话conjunction是「和」,disjunction是「或」- 同是英文,
en和en-GB的逗号规则也不同 - 要给每一项加样式,用
formatToParts()
同样三个词,不同语言连出来不一样
比如一个课程详情页要显示「本课程涵盖 HTML、CSS和JavaScript」,站点同时有中英文版。
const items = ['HTML', 'CSS', 'JavaScript']
const format = (locale, type) => new Intl.ListFormat(locale, { type }).format(items)
console.log(format('zh-CN', 'conjunction')) // 中文「和」
console.log(format('zh-CN', 'disjunction')) // 中文「或」
console.log(format('en', 'conjunction')) // 美式英文
console.log(format('en-GB', 'conjunction')) // 英式英文
console.log(format('de', 'conjunction')) // 德语查看输出与解释
HTML、CSS和JavaScript
HTML、CSS或JavaScript
HTML, CSS, and JavaScript
HTML, CSS and JavaScript
HTML, CSS und JavaScript中文前面用顿号,最后一项用「和」,而且中间不加空格。美式英文最后一项前的逗号叫牛津逗号,英式英文一般不加。这种细节自己用 join 去适配,写几个 if 就乱了,而且每加一种语言都要改代码。
只有两项时,中文会输出「张三和李四」,不带顿号;只有一项时原样返回;空数组返回空字符串。这些边界 Intl.ListFormat 都处理好了。
给每一项加链接:formatToParts()
实际页面里,列表中的名字常常要做成可点击的链接或者加粗。这时拿到拼好的字符串就没用了,要用 formatToParts()。
const lf = new Intl.ListFormat('zh-CN')
const parts = lf.formatToParts(['张三', '李四', '王五'])
// element 是列表项,literal 是连接用的标点和词
const html = parts
.map((p) => (p.type === 'element' ? `<a>${p.value}</a>` : p.value))
.join('')
console.log(html)查看输出与解释
<a>张三</a>、<a>李四</a>和<a>王五</a>formatToParts() 返回一个数组,每一段有 type 和 value。element 是你传进去的项目,literal 是语言规则加进来的顿号、「和」、逗号。渲染时把 element 包成链接,literal 原样输出,语言规则就完整保留了。
在 React 里不要拼 HTML 字符串,把 element 映射成 <a> 组件、literal 作为普通文本节点就行。用户名这类内容直接拼进 dangerouslySetInnerHTML 会有 XSS 风险,示例里的字符串拼接只是为了打印出来看。
容易答错的地方
- 先
join成一个字符串再交给format() format()需要一个数组,它要知道一共有几项、哪一项是最后一项,才能决定在哪里放「和」。传进去一个拼好的字符串,它只会当成一项原样返回。另外数组里的元素必须是字符串,传数字会抛TypeError,要先转成字符串。- 以为它会翻译列表项
- 它只处理连接的语法。「苹果、香蕉」要显示成英文,得先从翻译资源里拿到 apple 和 banana,再交给英文的 formatter。
面试官还会怎么问?
conjunction 和 disjunction 能随便换吗?
不能,它们的意思不一样。conjunction 是都成立,「支持 Chrome 和 Firefox」;disjunction 是选一个,「用 Chrome 或 Firefox 打开」。换了连接词,句子的意思就变了。
type: 'unit' 用在什么场景?
用来组合带单位的量,比如身高「5 feet, 7 inches」、时长「1 小时 30 分钟」。它不表示「和」也不表示「或」,只是把几个单位量排在一起。配合 style: 'narrow',英文会输出更紧凑的「5 feet 7 inches」。
浏览器兼容性怎么样?
主流浏览器的新版本都已支持,Chrome 从 72 版开始就有。要兼容更老的环境,可以用 FormatJS 提供的 polyfill,或者在不支持时退回到按语言手写的简单规则。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。