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

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

原文: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 在不牺牲性能的情况下实现相对时间的本地化格式化。

用法与示例

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

 
 
  1. const rtf = new Intl.RelativeTimeFormat('en');


  2. rtf.format(3.14, 'second');

  3. // → 'in 3.14 seconds'


  4. rtf.format(-15, 'minute');

  5. // → '15 minutes ago'


  6. rtf.format(8, 'hour');

  7. // → 'in 8 hours'


  8. rtf.format(-2, 'day');

  9. // → '2 days ago'


  10. rtf.format(3, 'week');

  11. // → 'in 3 weeks'


  12. rtf.format(-5, 'month');

  13. // → '5 months ago'


  14. rtf.format(2, 'quarter');

  15. // → 'in 2 quarters'


  16. rtf.format(-42, 'year');

  17. // → '42 years ago'

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

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

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


  2. rtf.format(3.14, 'second');

  3. // → '3.14秒钟后'


  4. rtf.format(-15, 'minute');

  5. // → '15分钟前'


  6. rtf.format(8, 'hour');

  7. // → '8小时后'


  8. rtf.format(-2, 'day');

  9. // → '2天前'


  10. rtf.format(3, 'week');

  11. // → '3周后'


  12. rtf.format(-5, 'month');

  13. // → '5个月前'


  14. rtf.format(2, 'quarter');

  15. // → '2个季度后'


  16. rtf.format(-42, 'year');

  17. // → '42年前'

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

 
 
  1. // 创建一个简体中文相对时间格式化示例,使用默认设置。

  2. // 在这个例子中,我们将默认参数显式的传进去

  3. const rtf = new Intl.RelativeTimeFormat('zh', {

  4. localeMatcher: 'best fit', // 其他值: 'lookup'

  5. style: 'long', // 其他值: 'short' 或 'narrow'

  6. numeric: 'always', // 其他值: 'auto'

  7. });


  8. rtf.format(-1, 'day');

  9. // → '1天前'


  10. rtf.format(0, 'day');

  11. // → '0天后'


  12. rtf.format(1, 'day');

  13. // → '1天后'


  14. rtf.format(-1, 'week');

  15. // → '1周前'


  16. rtf.format(0, 'week');

  17. // → '0周后'


  18. rtf.format(1, 'week');

  19. // → '1周后'

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

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

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


  2. rtf.format(-1, 'day');

  3. // → '昨天'


  4. rtf.format(-2, 'day');

  5. // → '前天'


  6. rtf.format(0, 'day');

  7. // → '今天'


  8. rtf.format(1, 'day');

  9. // → '明天'


  10. rtf.format(2, 'day');

  11. // → '后天'


  12. rtf.format(-1, 'week');

  13. // → '上周'


  14. rtf.format(0, 'week');

  15. // → '本周'


  16. rtf.format(1, 'week');

  17. // → '下周'

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

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


  2. rtf.format(-1, 'day');

  3. // → '昨天'


  4. rtf.formatToParts(-1, 'day');

  5. // → [{ type: 'literal', value: '昨天' }]


  6. rtf.format(3, 'week');

  7. // → '3周后'


  8. rtf.formatToParts(3, 'week');

  9. // → [

  10. //  { type: 'integer', value: '3', unit: 'week' },

  11. //  { type: 'literal', value: '周后' }

  12. // ]

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

结论

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

相关链接


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值