乐趣区

内置于浏览器中的国际化API

作者:wanago

翻译:疯狂的技术宅

https://wanago.io/2019/09/02/…

未经允许严禁转载

你的程序很有可能需要支持多种语言。其中包括对语言敏感的日期处理。一个广受欢迎的库 Moment.js 有助于实现这一目标,它的功能之一是 国际化。其源代码中包含对许多不同语言的本地化。现在这可能已经不是最好的方法了,因为我们有 ECMAScript 国际化 API。

国际化 API 旨在提供许多应用所需的语言敏感功能。它可以帮助你完成需要考虑语言的任务。浏览器将所有上述功能保留在 Intl 全局对象中,以避免发生命名冲突。

使用 DateTimeFormat 处理日期

Intl.DateTimeFormat 是一个构造函数,它允许我们进行语言敏感的日期处理。

const date = Date.now();
console.log(new Intl.DateTimeFormat('en-US').format(date)); //  8/30/2019
console.log(new Intl.DateTimeFormat('zh-ch').format(date)); //  2019/8/30

它不仅仅能够对日期中数字的规则进行格式化。通过提供额外的选项,还可以委托它翻译诸如周和月的字符串。

new Intl.DateTimeFormat(
  'zh-CN',
  { 
    weekday: 'short',
    month: 'long',
    day: '2-digit'
  }
).format(date)

输出:9 月 05 日周四

通过选择传递给 DateTimeFormat 构造函数的内容,我们可以根据需要对结果进行调整。我们可以将工作日、时代和月份等属性设置为 longshortnarrow。年和日的数值可以设置为 numeric(例如,1)或 2-digit(例如,01)。月份可以表示为数字或字符串。

我们还可以指定是否要用 12 小时制。此处的默认设置取决于区域设置。

new Intl.DateTimeFormat(
  'zh-CN',
  { 
    day: '2-digit',
    month: 'long',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    hour12: true
  }
).format(date)

2019 年 9 月 05 日 上午 11:41

你还可以使用其他一些选项。有关完整列表,请转到 MDN 进行查看。

MDN Docs 还提到了 dateStyletimeStyle。那些属性目前处于阶段 -3

相对时间格式

通过 ECMAScript 国际化 API,还可以根据所提供的语言处理相对时间的格式。

const formatter = new Intl.RelativeTimeFormat('en');
formatter.format(-1, 'day'); // 1 day ago

通过将 numeric 设置为 auto,我们也可以使用字符串值(如果可用的话)。

const formatter = new Intl.RelativeTimeFormat('en', { numeric: 'auto'});
formatter.format(-1, 'day'); // yesterday

通过将 style 设置为 long,short 或 narrow,可以配置消息的长度。

const formatter = new Intl.RelativeTimeFormat('en', { style: 'long'});
formatter.format(5, 'year'); // in 5 years
const formatter = new Intl.RelativeTimeFormat('en', { style: 'short'});
formatter.format(5, 'year'); // in 5 yr.

narrow 风格可能类似于某些地区的短风格。

用 Luxon 替换 Moment.js

你可能不愿意用原生 Date API 替换 Moment.js 库的许多有用功能。Luxon 是一个有趣的选择。这个项目是由 Moment.js 维护者之一发起的,他们希望提供一些不同的 API,但不想在 Moment.js 中破坏任何东西。通过从头编写新库,他能够改变一些重要的事情。最重要的是 Luxon 使用了国际化 API。多亏了这一点,它不必像 Moment 那样发布国际化文件。

我们还需要考虑浏览器支持。Sine Luxon 专注于使用原生 API,但并非每个浏览器都能完整的支持。如果你对此担心的话,也可以考虑使用 polyfill。有关详细信息,请查看 support matrix。

国际化 API 其他很酷的功能

ECMAScript Internationalization API 提供了其他有用的功能。其中之一是格式化列表的能力。

使用 Intl.ListFormat 格式化列表

const list = ['Cat', 'Dog', 'Rat'];
new Intl.ListFormat('en-GB', { style: 'long', type: 'conjunction'}).format(list);

Cat, Dog and Rat

const list = ['Cat', 'Dog', 'Rat'];
new Intl.ListFormat('en-US', { style: 'long', type: 'conjunction'}).format(list);

Cat, Dog, and Rat

注意,此 API 非常精确,甚至考虑到了相当微妙的差异,例如在英国和美国英语的 and 之前使用 serial comma。

语言敏感的字符串比较

另一个很有用的功能是 collator 功能。在比较可能包含某些特定于语言的字符的字符串时会派上用场。“ä”字母是一个很好的例子,因为它出现在德语和瑞典语的字母表中时的顺序可能不同。

new Intl.Collator('de').compare('ä', 'z'); // -1
new Intl.Collator('sv').compare('ä', 'z'); // 1

你可以把许多选项传递给 collator 函数。在 MDN docs 中可以找到一个列表

多个规则

通过使用 Intl.PluralRules,我们可以使用多个敏感格式。

例如,你可以用它来确定在指定语言中使用的复数形式。

new Intl.PluralRules('en-US').select(1); // one

函数返回“one”,所以正确的形式将是“one dog”。

new Intl.PluralRules('en-US').select(41); // other

函数返回“other”,所以正确的形式将是“fourty one dogs”。

另一个用例是找出序数。

new Intl.PluralRules('en-US', { type: 'ordinal'}).select(41); // one

由于函数的结果为“one”,序数为:41

new Intl.PluralRules('en-US', { type: 'ordinal'}).select(32); // two

因为结果为“2”,序数为:32

格式化数字

格式编号中的规则因语言和国家地区而异。使用 Intl.NumberFormat 可以为给定国家 / 地区使用正确的格式。

const number = 1025.15;
new Intl.NumberFormat('en-US').format(number); // 1,025.15
new Intl.NumberFormat('ar-EG').format(number); // 输出奇怪的阿拉伯文

你可以使用许多不同的选项。

const number = 125.5678;
new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY'}).format(number); //¥1,025.15
new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP'}).format(number); // £125.57

总结

在本文中,我们了解了 ECMAScript Internationalization API 的基本功能。它可能在很多场合对你有用。我相信知道它能够提供什么是有必要,这样我们就不必再去寻找能够做同样事情的外部库。并非所有浏览器都支持上述功能,记得在使用钱先进行检查,在必要时可以使用 polyfills。


本文首发微信公众号:前端先锋

欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章

欢迎继续阅读本专栏其它高赞文章:

  • 深入理解 Shadow DOM v1
  • 一步步教你用 WebVR 实现虚拟现实游戏
  • 13 个帮你提高开发效率的现代 CSS 框架
  • 快速上手 BootstrapVue
  • JavaScript 引擎是如何工作的?从调用栈到 Promise 你需要知道的一切
  • WebSocket 实战:在 Node 和 React 之间进行实时通信
  • 关于 Git 的 20 个面试题
  • 深入解析 Node.js 的 console.log
  • Node.js 究竟是什么?
  • 30 分钟用 Node.js 构建一个 API 服务器
  • Javascript 的对象拷贝
  • 程序员 30 岁前月薪达不到 30K,该何去何从
  • 14 个最好的 JavaScript 数据可视化库
  • 8 个给前端的顶级 VS Code 扩展插件
  • Node.js 多线程完全指南
  • 把 HTML 转成 PDF 的 4 个方案及实现

  • 更多文章 …
退出移动版