You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用RelativeTimeFormat.formatToParts实现本地化时长展示?

如何提取RelativeTimeFormat中的本地化单位(剥离方向词)

这个问题确实戳中了Intl.RelativeTimeFormat的一个小痛点——它的formatToParts方法并没有把方向词(比如英文的"in"/"ago"、中文的"前"/"后")和单位词("秒"/"second")分开标记,导致我们没法直接提取纯粹的本地化单位。不过别担心,我们可以利用多语言下时间表述的共性来解决这个问题。

核心思路

对于任意语言,同一个时间单位的“未来”和“过去”表述,差异只在方向词,单位词是完全一致的。比如:

  • 英文:未来是in 1 second,过去是1 second ago → 共同单位是second
  • 中文:未来是1秒后,过去是1秒前 → 共同单位是秒
  • 西班牙语:未来是en 1 minuto,过去是hace 1 minuto → 共同单位是minuto

我们可以利用这个共性,通过以下步骤提取单位:

  1. 用Intl.NumberFormat生成本地化的数字字符串(比如英文的"1"、阿拉伯语的"١")
  2. 用RelativeTimeFormat分别生成未来(+1单位)和过去(-1单位)的完整字符串
  3. 从两个字符串中移除本地化数字,得到仅包含方向词和单位的部分
  4. 找出这两部分的最长公共子串,就是我们需要的本地化单位

代码实现

function getLocalizedDurationUnit(locale, unit) {
  // 生成本地化的数字"1"
  const numFormatter = new Intl.NumberFormat(locale);
  const localizedNum = numFormatter.format(1);
  
  // 初始化RelativeTimeFormat(确保numeric为always,避免"a second"这类非数字表述)
  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'always' });
  const futureStr = rtf.format(1, unit);
  const pastStr = rtf.format(-1, unit);
  
  // 移除数字部分,得到方向词+单位的组合
  const futureWithoutNum = futureStr.replace(localizedNum, '').trim();
  const pastWithoutNum = pastStr.replace(localizedNum, '').trim();
  
  // 寻找两个字符串的最长公共子串(即单位词)
  function longestCommonSubstring(strA, strB) {
    let longestMatch = '';
    for (let i = 0; i < strA.length; i++) {
      for (let j = i + 1; j <= strA.length; j++) {
        const substring = strA.slice(i, j);
        if (strB.includes(substring) && substring.length > longestMatch.length) {
          longestMatch = substring;
        }
      }
    }
    return longestMatch.trim();
  }
  
  return longestCommonSubstring(futureWithoutNum, pastWithoutNum);
}

// 测试示例
console.log(getLocalizedDurationUnit('en-US', 'second')); // "second"
console.log(getLocalizedDurationUnit('zh-CN', 'second')); // "秒"
console.log(getLocalizedDurationUnit('es-ES', 'minute')); // "minuto"
console.log(getLocalizedDurationUnit('ar-SA', 'hour')); // "ساعة"

适配你的页面生成时间场景

当你需要展示“页面生成时间:X秒”这类内容时,可以这样组合使用:

const userLocale = navigator.language; // 获取用户浏览器的本地化语言
const pageLoadTime = 2; // 实际页面生成时长(秒)
const timeUnit = 'second';

// 获取本地化单位
const localizedUnit = getLocalizedDurationUnit(userLocale, timeUnit);
// 生成本地化数字
const localizedNum = new Intl.NumberFormat(userLocale).format(pageLoadTime);

// 处理复数(部分语言需要,比如英文的"second"/"seconds")
const rtf = new Intl.RelativeTimeFormat(userLocale, { numeric: 'always' });
const fullPastStr = rtf.format(-pageLoadTime, timeUnit);
const pastWithoutNum = fullPastStr.replace(localizedNum, '').trim();
// 剥离方向词,得到带复数的单位组合
const durationStr = fullPastStr.replace(pastWithoutNum, '');

// 最终展示字符串
const displayText = `页面生成时间:${durationStr}`;
console.log(displayText);
// 英文输出:页面生成时间:2 seconds
// 中文输出:页面生成时间:2秒

这个方案完全依赖浏览器原生的Intl API,不需要维护多语言单位词库,能完美适配各种本地化场景。

内容的提问来源于stack exchange,提问作者Sora2455

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:06:44