资讯专栏INFORMATION COLUMN

国际化相对时间格式化API:Intl.RelativeTimeFormat

Richard_Gao / 560人阅读

摘要:在不牺牲性能的情况下实现相对时间的本地化格式化。用法与示例以下示例展示了如何使用英语创建相对时间格式化程序。需要注意的是传递给构造函数的参数必须是一个语言标记,或者是一个包括多个语言标记的数组。

原文:The Intl.RelativeTimeFormat API
作者:Mathias Bynens(@mathias)

现代 Web 应用程序通常使用“昨天”,“42秒前”或“3个月”之类的短语,而不是完整的日期和时间戳。这种相对时间格式已经变得非常普遍,以至于几个流行的库都实现了本地化格式化的函数。(例如 Moment.js,Globalize 和 date-fns。)

实现本地化相对时间格式化的一个问题是,您需要为每种语言提供习惯词或短语列表(例如“昨天”或“上一季度”)。Unicode CLDR 提供了此数据,但要在 JavaScript 中使用它,必须将其嵌入到库代码中一起提供。遗憾的是,这无疑会增加这些库的包大小,这会影响到脚本的加载时间、解析/编译成本和内存消耗。

全新的 Intl.RelativeTimeFormat API 将此负担转移到了 JavaScript 引擎,JavaScript 引擎可以提供语言环境数据并使其直接供 JavaScript 开发人员使用。 Intl.RelativeTimeFormat 在不牺牲性能的情况下实现相对时间的本地化格式化。

用法与示例

以下示例展示了如何使用英语创建相对时间格式化程序。

const rtf = new Intl.RelativeTimeFormat("en");

rtf.format(3.14, "second");
// → "in 3.14 seconds"

rtf.format(-15, "minute");
// → "15 minutes ago"

rtf.format(8, "hour");
// → "in 8 hours"

rtf.format(-2, "day");
// → "2 days ago"

rtf.format(3, "week");
// → "in 3 weeks"

rtf.format(-5, "month");
// → "5 months ago"

rtf.format(2, "quarter");
// → "in 2 quarters"

rtf.format(-42, "year");
// → "42 years ago"

需要注意的是传递给 Intl.RelativeTimeFormat 构造函数的参数必须是一个 BCP 47 语言标记,或者是一个包括多个语言标记的数组。

以下是使用其他语言(汉语简体中文)的示例:(译注:原文是西班牙语)

const rtf = new Intl.RelativeTimeFormat("zh"); // 或 "zh-Hans-CN"

rtf.format(3.14, "second");
// → "3.14秒钟后"

rtf.format(-15, "minute");
// → "15分钟前"

rtf.format(8, "hour");
// → "8小时后"

rtf.format(-2, "day");
// → "2天前"

rtf.format(3, "week");
// → "3周后"

rtf.format(-5, "month");
// → "5个月前"

rtf.format(2, "quarter");
// → "2个季度后"

rtf.format(-42, "year");
// → "42年前"

此外,Intl.RelativeTimeFormat 构造函数还接受一个可选 options 参数,该参数可以对输出进行细粒度控制。为了说明灵活性,让我们根据默认设置查看更多输出:

// 创建一个简体中文相对时间格式化示例,使用默认设置。
// 在这个例子中,我们将默认参数显式的传进去
const rtf = new Intl.RelativeTimeFormat("zh", {
 localeMatcher: "best fit", // 其他值: "lookup"
 style: "long", // 其他值: "short" 或 "narrow"
 numeric: "always", // 其他值: "auto"
});

rtf.format(-1, "day");
// → "1天前"

rtf.format(0, "day");
// → "0天后"

rtf.format(1, "day");
// → "1天后"

rtf.format(-1, "week");
// → "1周前"

rtf.format(0, "week");
// → "0周后"

rtf.format(1, "week");
// → "1周后"

您可能已经注意到上面的格式化程序生成了字符串 "1天前" 而不是 "昨天",还有显得比较弱智的 "0周后" 而不是 "本周"。发生这种情况是因为默认情况下,格式化程序使用数值进行输出。

要更改此行为,请将 numeric 选项设置为 "auto"(默认值是 "always"):

const rtf = new Intl.RelativeTimeFormat("zh", { numeric: "auto" });

rtf.format(-1, "day");
// → "昨天"

rtf.format(-2, "day");
// → "前天"

rtf.format(0, "day");
// → "今天"

rtf.format(1, "day");
// → "明天"

rtf.format(2, "day");
// → "后天"

rtf.format(-1, "week");
// → "上周"

rtf.format(0, "week");
// → "本周"

rtf.format(1, "week");
// → "下周"

Analogous to other Intl classes, Intl.RelativeTimeFormat has a formatToParts method in addition to the format method. Although format covers the most common use case, formatToParts can be helpful if you need access to the individual parts of the generated output:

与其他 Intl 类一样,Intl.RelativeTimeFormat 除了 format 方法之外,还有一个 formatToParts 方法。虽然 format 涵盖了最常见的用例,但如果您需要访问生成的输出的各个部分,formatToParts 会很有帮助:

const rtf = new Intl.RelativeTimeFormat("zh", { numeric: "auto" });

rtf.format(-1, "day");
// → "昨天"

rtf.formatToParts(-1, "day");
// → [{ type: "literal", value: "昨天" }]

rtf.format(3, "week");
// → "3周后"

rtf.formatToParts(3, "week");
// → [
//  { type: "integer", value: "3", unit: "week" },
//  { type: "literal", value: "周后" }
// ]

有关其余选项及其行为的详细信息,请参阅 API docs in the proposal repository.

结论

Intl.RelativeTimeFormat 默认情况下在 V8 v7.1.179 和 Chrome 71 中可用。随着此 API 变得更加广泛可用,您将发现诸如 Moment.js、Globalize、date-fns 之类的库,会从代码库中移除对硬编码 CLDR 数据库的依赖性,而使用本机相对时间格式化功能,从而提高加载时性能、分析和编译时性能、运行时性能和内存使用。

相关链接

Intl.RelativeTimeFormat Spec Proposal

The ECMAScript Internationalization API

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98596.html

相关文章

  • 精读《What's new in javascript》

    摘要:举例来说即便某个失败了,也不会导致的发生,这样在不在乎是否有项目失败,只要拿到都结束的信号的场景很有用。对于则稍有不同只要有子项,就会完成,哪怕第一个了,而第二个了,也会,而对于,这种场景会直接。 1. 引言 本周精读的内容是:Google I/O 19。 2019 年 Google I/O 介绍了一些激动人心的 JS 新特性,这些特性有些已经被主流浏览器实现,并支持 polyfill...

    dabai 评论0 收藏0
  • FE.ES-了解JS数据本土化

    摘要:相对时间本土化支持昨天前天数字本土化分组逗号分隔科学计数保留位小数保留位百分制货币人民币汉字一二三四五六七八九一二三四五六二日期时间本土化时间本土化上午日期本土化配置项 相对时间本土化 支持 second, minute, hour, day, week, month, quarter, year var rtf = new Intl.RelativeTimeFormat(zh-Han...

    zqhxuyuan 评论0 收藏0
  • What's New in JavaScript

    摘要:在和中都保留了数组的强引用,所以在中简单的清除变量内存并没有得到释放,因为还存在引用计数。而在中,它的键是弱引用,不计入引用计数中,所以当被清除之后,数组会因为引用计数为而被回收掉。其实我们主要注意的引用是不计引用计数的,就好理解了。 showImg(https://segmentfault.com/img/remote/1460000019147368?w=900&h=383); 前...

    cgh1999520 评论0 收藏0
  • ECMASCript 2019可能会有哪些特性?

    摘要:可能不会包括所有的语法提案。事实上,有些提案已经被搁置很多年了。因此,很可能也会在今年月份发布。 译者按: 又过了1年... 原文:Whats New in JavaScript for 2019 译者: Fundebug 为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。 最近这些年,ECMASCript标准发展节奏非常稳定,每年都会发布新的特...

    tuantuan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<