如何在 JavaScript 中使用语言特定的分隔符格式化数组?
使用 Intl.ListFormat 自动为任何语言应用正确的逗号、空格和标点符号。
介绍
当您将数组转换为可读的字符串时,需要用逗号或其他标点符号分隔各项。不同语言使用不同的分隔符。英语使用逗号和空格,日语使用顿号「、」,而阿拉伯语则使用不同的标点符号和词序。
Intl.ListFormat API 可以将数组转换为带有适合语言环境的分隔符的字符串。这确保了您的列表在每种语言中看起来都很自然。
为什么数组分隔符因语言环境而异
您可能会认为所有语言都使用逗号来分隔列表项。但事实并非如此。
英语使用逗号和空格分隔项。
// 英语: "red, green, blue"
日语使用顿号「、」,且不加空格。
// 日语: "赤、緑、青"
中文使用相同的顿号「、」。
// 中文: "红、绿、蓝"
阿拉伯语使用不同的逗号字符「،」,并从右到左书写。
// 阿拉伯语: "أحمر، أخضر، أزرق"
这些差异在 Intl.ListFormat 中是自动处理的。您无需了解每种语言的标点规则。
join() 的问题
Array.prototype.join() 方法使用您指定的分隔符将数组转换为字符串。
const colors = ["red", "green", "blue"];
console.log(colors.join(", "));
// "red, green, blue"
这会硬编码英语的标点符号。逗号和空格的分隔符不适用于其他语言。
const colors = ["赤", "緑", "青"];
console.log(colors.join(", "));
// "赤, 緑, 青" (错误 - 应使用「、」而不是「,」)
您无法手动根据语言环境切换分隔符,因为这需要维护一个每种语言及其标点规则的映射。这种映射既不完整,也难以维护。
使用 Intl.ListFormat 实现符合语言习惯的分隔符
Intl.ListFormat 构造函数创建一个格式化器,用于为任何语言环境应用正确的分隔符。
const formatter = new Intl.ListFormat("en");
const colors = ["red", "green", "blue"];
console.log(formatter.format(colors));
// "red, green, and blue"
格式化器会自动使用指定语言环境的正确标点符号。您可以将语言环境代码作为第一个参数传递。
const enFormatter = new Intl.ListFormat("en");
const jaFormatter = new Intl.ListFormat("ja");
const arFormatter = new Intl.ListFormat("ar");
const colors = ["red", "green", "blue"];
console.log(enFormatter.format(colors));
// "red, green, and blue"
console.log(jaFormatter.format(["赤", "緑", "青"]));
// "赤、緑、青"
console.log(arFormatter.format(["أحمر", "أخضر", "أزرق"]));
// "أحمر، أخضر، أزرق"
浏览器提供了标点规则。您无需维护任何特定语言环境的代码。
不同语言中的分隔符变化
格式化器会根据语言环境应用不同的分隔符。以下示例展示了相同数组在不同语言中的格式化方式。
英语使用逗号、空格和单词 "and"。
const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["apple", "orange", "banana"]));
// "apple, orange, and banana"
西班牙语使用逗号、空格和单词 "y"。
const formatter = new Intl.ListFormat("es");
console.log(formatter.format(["manzana", "naranja", "plátano"]));
// "manzana, naranja y plátano"
法语使用逗号、空格和单词 "et"。
const formatter = new Intl.ListFormat("fr");
console.log(formatter.format(["pomme", "orange", "banane"]));
// "pomme, orange et banane"
德语使用逗号、空格和单词 "und"。
const formatter = new Intl.ListFormat("de");
console.log(formatter.format(["Apfel", "Orange", "Banane"]));
// "Apfel, Orange und Banane"
日语使用列举逗号 、 和字符 、。
const formatter = new Intl.ListFormat("ja");
console.log(formatter.format(["りんご", "オレンジ", "バナナ"]));
// "りんご、オレンジ、バナナ"
中文使用列举逗号 、 和单词 和。
const formatter = new Intl.ListFormat("zh");
console.log(formatter.format(["苹果", "橙子", "香蕉"]));
// "苹果、橙子和香蕉"
韩语使用逗号和助词 및。
const formatter = new Intl.ListFormat("ko");
console.log(formatter.format(["사과", "오렌지", "바나나"]));
// "사과, 오렌지 및 바나나"
格式化器会自动处理所有这些差异。您可以为每种语言编写相同的代码。
使用用户的语言环境
您可以从用户的浏览器设置中检测其首选语言环境,并使用它来格式化列表。
const userLocale = navigator.language;
const formatter = new Intl.ListFormat(userLocale);
const items = ["first", "second", "third"];
console.log(formatter.format(items));
这可以确保列表使用符合用户期望的分隔符。使用法语浏览器设置的用户会看到法语标点符号,而使用日语设置的用户会看到日语标点符号。
格式化不带连接词的数组
默认的 Intl.ListFormat 行为会在最后一项之前添加一个连接词,例如“和”。您可以通过使用单元类型来禁用此功能。
const formatter = new Intl.ListFormat("en", { type: "unit" });
console.log(formatter.format(["5 km", "12 minutes", "100 calories"]));
// "5 km, 12 minutes, 100 calories"
单元类型仅使用分隔符,而不添加连接词。这对于技术列表、测量值或不适合使用连接词的数据非常有用。
const enFormatter = new Intl.ListFormat("en", { type: "unit" });
const jaFormatter = new Intl.ListFormat("ja", { type: "unit" });
console.log(enFormatter.format(["Item A", "Item B", "Item C"]));
// "Item A, Item B, Item C"
console.log(jaFormatter.format(["項目A", "項目B", "項目C"]));
// "項目A、項目B、項目C"
即使没有连接词,分隔符标点仍然遵循语言环境规则。
创建可重用的格式化器
您可以创建一个格式化器并将其用于多个数组。这比为每个数组创建一个新的格式化器更高效。
const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["red", "green"]));
// "red and green"
console.log(formatter.format(["a", "b", "c", "d"]));
// "a, b, c, and d"
console.log(formatter.format(["one"]));
// "one"
同一个格式化器适用于任意长度的数组。它会根据数组中的项数应用正确的分隔符和连接词。
处理空数组
当格式化一个空数组时,格式化器会返回一个空字符串。
const formatter = new Intl.ListFormat("en");
console.log(formatter.format([]));
// ""
如果需要不同的行为,您应该在格式化之前检查数组是否为空。
function formatList(items, locale) {
if (items.length === 0) {
return "没有项目";
}
const formatter = new Intl.ListFormat(locale);
return formatter.format(items);
}
console.log(formatList([], "en"));
// "没有项目"
console.log(formatList(["apple"], "en"));
// "apple"
这样可以让您控制空数组在用户面前的显示方式。
浏览器支持
Intl.ListFormat API 在所有现代浏览器中都可用。从 2021 年 4 月起,Chrome、Firefox、Safari 和 Edge 都已支持该 API。
在使用之前,您可以检查该 API 是否存在。
if (typeof Intl.ListFormat !== "undefined") {
const formatter = new Intl.ListFormat("en");
console.log(formatter.format(["a", "b", "c"]));
} else {
console.log("Intl.ListFormat 不受支持");
}
对于较旧的浏览器,您可以回退到使用 join() 方法。这种方法提供了基本的格式化,但没有语言特定的分隔符。
function formatList(items, locale) {
if (typeof Intl.ListFormat !== "undefined") {
const formatter = new Intl.ListFormat(locale);
return formatter.format(items);
}
return items.join(", ");
}
console.log(formatList(["red", "green", "blue"], "en"));
// "red, green, and blue"(或在较旧的浏览器中为 "red, green, blue")
这可以确保您的代码在所有浏览器中都能运行,同时在现代浏览器中提供最佳体验。