VueUse 中的 useTimeAgo 函数的国际化和浏览器内置国际化API

看到一个帖子提到了 VueUse 中的一个函数 useTimeAgo,比较好奇这个函数是干什么的就点开了帖子看了一下。
其实就是一个相对时间对比的函数,输入一个目标时间(允许时间戳或者格式化日期字符串),返回目标距离现在的文本内容。

举个例子:

import { useTimeAgo } from '@vueuse/core'

useTimeAgo(new Date()) // just now
useTimeAgo(new Date('2024-06-01')) // 2 weeks ago

但是 useTimeAgo 函数返回的文本内容是固定的英文字符串。所以,如果在中文环境下使用就可能会被挑战说需要展示中文的相对时间文本。
🔗 vueuse/packages/core/useTimeAgo/index.ts at main · vueuse/vueuse

看了一下 useTimeAgo 的实现,是支持自己做一份国际化配置,然后传入给 useTimeAgo 方法来使用的。

👇 举个中文版本的例子(你也可以使用 vue-i18n 实现多语言的版本):

const options = {
  messages: {
      justNow: '刚刚', 
      past: n => n.match(/\d/) ? `${n}前` : n,
      future: n => n.match(/\d/) ? `${n}后` : n,
      month: (n, past) => n === 1
        ? past
          ? '上个月'
          : '下个月'
        : `${n}个月`,
      year: (n, past) => n === 1
        ? past
          ? '去年'
          : '明年'
        : `${n}年`,
      day: (n, past) => n === 1
        ? past
          ? '昨天'
          : '明天'
        : `${n}天`,
      week: (n, past) => n === 1
        ? past
          ? '上周'
          : '下周'
        : `${n}周`,
      hour: n => `${n}小时`,
      minute: n => `${n}分钟`,
      second: n => `${n}秒`,
      invalid: '无效值',
  }
}

const timeAgo = useTimeAgo(new Date(), options) // 刚刚

好的,在 VueUse 中的使用已经解决了。

并且我在寻找解决发现了一个浏览器内置的 API 👉 Intl.RelativeTimeFormat
非常简单易用,使用 new Intl.RelativeTimeFormat() 创建好 Intl.RelativeTimeFormat 实例之后,使用实例上的 format(value, unit) 方法就可以输出转换好的相对时间文本。

  • value 是时间差值
  • unit 是时间单位
    • 有效值有: year, quarter, month, week, day, hour, minute, second

举个例子:

const rtf = new Intl.RelativeTimeFormat('zh');

rtf.format(3, 'day') // 3天后
rtf.format(0, 'day') // 0天后
rtf.format(-1, 'day') // 1天前

rtf.format(-1, 'year') // 1年前

但是就很回比较“傻”,不会自动转换成 “昨天”、“今天”、“明天”这样的。所以可以配置 numeric: auto 来改变输出的文本内容 👇

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

rtf.format(3, 'day') // 3天后
rtf.format(1, 'day') // 明天
rtf.format(0, 'day')
rtf.format(-1, 'day') // 昨天
rtf.format(-35, 'day') // 35天前

Using the auto option

If numeric:auto option is passed, it will produce the string yesterday, today, or tomorrow instead of 1 day ago, in 0 days, or in 1 day. This allows to not always have to use numeric values in the output.

不过也会有一些问题,因为必须要传入 unit 参数,所以如果事固定值的话,就会出现 35天前 这样的文本,而不是 一个月前,但也足够使用了。

以上。


相关文档

useTimeAgo | VueUse
vueuse/packages/core/useTimeAgo/index.ts at main · vueuse/vueuse
Intl.RelativeTimeFormat - JavaScript | MDN

How to use useTimeAgo to display in Chinese · Issue #3356 · vueuse/vueuse
Translations for useTimeAgo · Issue #1592 · vueuse/vueuse

前端大佬们有没有好用的 timeago 库 - V2EX