JavaScript Intl API 本地化实战:全面掌握数字货币日期与排序

一、为什么选择 Intl API 而非第三方库

长期以来,前端国际化方案依赖于 moment.jsi18next 等重量级库。这些库虽然在历史时期发挥过重要作用,但体积庞大,且许多功能已经被现代浏览器原生支持。ECMAScript Internationalization API(简称 Intl)是JavaScript内建的国际化解决方案,无需引入任何外部依赖即可完成数字格式化、货币显示、日期时间本地化、字符串排序、相对时间格式、列表连接等任务。它拥有以下核心优势:

  • 零体积:浏览器原生实现,打包体积无增加。
  • 高性能:底层由C++实现,速度远超纯JavaScript库。
  • 自动适配:根据用户操作系统语言和地区自动调整格式。
  • 标准化:符合ECMA-402规范,兼容现代所有主流浏览器。

本文将带你逐一攻克 Intl 的各个核心类,通过20多个可直接运行的实例,让你彻底摆脱对第三方格式化库的依赖。

二、Intl.NumberFormat:数字与货币格式化

数字在不同地区的表示方式差异巨大:小数点是逗号还是点?分组分隔符是什么?货币符号放在前面还是后面?Intl.NumberFormat 可以优雅地解决这些问题。

2.1 基本数字格式化

const number = 1234567.89;

// 默认为用户浏览器语言和国家
console.log(new Intl.NumberFormat().format(number));
// 美国英语输出: "1,234,567.89"

// 指定德语格式
console.log(new Intl.NumberFormat('de-DE').format(number));
// 输出: "1.234.567,89"

// 指定印地语格式
console.log(new Intl.NumberFormat('hi-IN').format(number));
// 输出: "12,34,567.89"  (印度的特殊分组规则)

通过 locales 参数可以显式指定语言标签(BCP 47),结合可选选项参数可实现更精细的控制。

2.2 货币格式化

货币格式化需指定 style: ‘currency’ 以及 currency 货币代码。

const price = 2999.5;

// 人民币
console.log(new Intl.NumberFormat('zh-CN', {
    style: 'currency',
    currency: 'CNY'
}).format(price));
// 输出: "¥2,999.50"

// 美元
console.log(new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD'
}).format(price));
// 输出: "$2,999.50"

// 欧元(德国)
console.log(new Intl.NumberFormat('de-DE', {
    style: 'currency',
    currency: 'EUR'
}).format(price));
// 输出: "2.999,50 €"

还可以设置 currencyDisplay‘name’‘code’ 来显示完整的货币名称或代码。

2.3 百分比与单位格式化

style: ‘percent’ 将数值乘以100并添加百分号;style: ‘unit’ 可用于长度、体积等单位。

// 百分比
console.log(new Intl.NumberFormat('en-US', {
    style: 'percent',
    minimumFractionDigits: 1
}).format(0.123));
// 输出: "12.3%"

// 单位(公里)
console.log(new Intl.NumberFormat('zh-CN', {
    style: 'unit',
    unit: 'kilometer'
}).format(15));
// 输出: "15公里"

三、Intl.DateTimeFormat:日期时间本地化

日期格式化是国际化中最常见的需求。Intl.DateTimeFormat 提供了极为丰富的选项,可以组合出几乎任何所需的日期时间格式。

3.1 基础日期格式

const date = new Date(2025, 5, 15, 14, 30, 0); // 2025年6月15日 14:30

// 用户本地格式
console.log(new Intl.DateTimeFormat().format(date));
// 中文浏览器通常输出: "2025/6/15"

// 美国英语
console.log(new Intl.DateTimeFormat('en-US').format(date));
// 输出: "6/15/2025"

// 英国英语
console.log(new Intl.DateTimeFormat('en-GB').format(date));
// 输出: "15/06/2025"

3.2 自定义组件:年月日与星期

通过 options 对象的 yearmonthdayweekday 等属性可精细控制输出内容。

const options = {
    weekday: 'long',
    year: 'numeric',
    month: 'long',
    day: 'numeric'
};

console.log(new Intl.DateTimeFormat('zh-CN', options).format(date));
// 输出: "2025年6月15日星期日"

console.log(new Intl.DateTimeFormat('en-US', options).format(date));
// 输出: "Sunday, June 15, 2025"

3.3 时间与时区

灵活显示时分秒,并支持时区转换。

const timeOptions = {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
    timeZone: 'America/New_York'
};

console.log(new Intl.DateTimeFormat('zh-CN', timeOptions).format(date));
// 根据北京时间转为纽约时间输出

3.4 相对时间格式:Intl.RelativeTimeFormat

显示“3天前”、“5分钟后”等相对时间描述。

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

console.log(rtf.format(-3, 'day'));   // "3天前"
console.log(rtf.format(1, 'week'));   // "1周后"
console.log(rtf.format(5, 'minute')); // "5分钟后"

// 使用 numeric: 'auto' 在可能时显示"昨天"等
const rtfAuto = new Intl.RelativeTimeFormat('zh-CN', { numeric: 'auto' });
console.log(rtfAuto.format(-1, 'day')); // "昨天"
console.log(rtfAuto.format(0, 'day'));  // "今天"

四、Intl.Collator:多语言字符串排序

JavaScript原生的 Array.prototype.sort() 默认按Unicode码点排序,对多语言用户会产生意想不到的顺序。Intl.Collator 提供了语言敏感的字符串比较器。

const names = ['张三', '李四', '王五', 'änna', 'Béla', 'Catherine'];

// 默认拼音排序(中文)
console.log(names.sort(new Intl.Collator('zh').compare));
// 大致按拼音顺序排列

// 德语排序
console.log(names.sort(new Intl.Collator('de').compare));

// 忽略大小写和变音符号
const collator = new Intl.Collator('en', {
    sensitivity: 'base',
    numeric: true  // 自然数字排序
});
const mixed = ['a10', 'a2', 'a1'];
console.log(mixed.sort(collator.compare));
// 输出: ["a1", "a2", "a10"]  (真正的数字顺序)

sensitivity 选项控制比较的敏感度:‘base’ 忽略大小写和变音符号,‘accent’ 区分变音符号但忽略大小写,‘case’ 区分大小写但忽略变音,‘variant’ 区分所有。

五、其他实用 Intl 功能

5.1 Intl.ListFormat:列表连接词

将数组中的项目按照语言习惯连接成字符串,如“A、B和C”。

const list = ['苹果', '香蕉', '橘子'];

console.log(new Intl.ListFormat('zh-CN', {
    style: 'long',
    type: 'conjunction'
}).format(list));
// 输出: "苹果、香蕉和橘子"

console.log(new Intl.ListFormat('en-US', {
    style: 'long',
    type: 'disjunction'
}).format(['apples', 'oranges', 'bananas']));
// 输出: "apples, oranges, or bananas"

5.2 Intl.DisplayNames:语言、货币、地区的显示名称

const displayNames = new Intl.DisplayNames('zh-CN', { type: 'language' });
console.log(displayNames.of('en'));  // "英语"
console.log(displayNames.of('de'));  // "德语"

const currencyNames = new Intl.DisplayNames('zh-CN', { type: 'currency' });
console.log(currencyNames.of('USD')); // "美元"
console.log(currencyNames.of('EUR')); // "欧元"

六、构建一个完整的本地化工具模块

基于上述API,我们可以封装一个轻量级的本地化工具,便于在项目中复用。以下模块自动检测用户语言,提供格式化数字、货币、日期和相对时间的方法:

// i18n.js
const userLocale = navigator.language || 'zh-CN';

export const formatNumber = (num, options = {}) => {
    return new Intl.NumberFormat(userLocale, options).format(num);
};

export const formatCurrency = (amount, currency = 'CNY') => {
    return new Intl.NumberFormat(userLocale, {
        style: 'currency',
        currency
    }).format(amount);
};

export const formatDate = (date, options = {}) => {
    return new Intl.DateTimeFormat(userLocale, options).format(new Date(date));
};

export const formatRelative = (diffValue, unit) => {
    const rtf = new Intl.RelativeTimeFormat(userLocale, { numeric: 'auto' });
    return rtf.format(diffValue, unit);
};

// 计算两个日期的相对描述
export const formatTimeAgo = (date) => {
    const now = Date.now();
    const past = new Date(date).getTime();
    const diffSeconds = Math.round((past - now) / 1000);
    const absDiff = Math.abs(diffSeconds);
    
    const units = [
        { unit: 'year', seconds: 31536000 },
        { unit: 'month', seconds: 2592000 },
        { unit: 'week', seconds: 604800 },
        { unit: 'day', seconds: 86400 },
        { unit: 'hour', seconds: 3600 },
        { unit: 'minute', seconds: 60 },
        { unit: 'second', seconds: 1 }
    ];
    
    for (const { unit, seconds } of units) {
        if (absDiff >= seconds || unit === 'second') {
            const value = Math.round(diffSeconds / seconds);
            return formatRelative(value, unit);
        }
    }
};

// 使用示例
console.log(formatCurrency(1299, 'CNY')); // ¥1,299.00
console.log(formatDate(new Date(), { dateStyle: 'full' })); 
console.log(formatTimeAgo('2025-05-20T12:00:00'));

这个轻量模块总计不超过50行代码,却覆盖了大多数国际化需求。无需引入任何第三方依赖,体积为零,性能极佳。

七、最佳实践与注意事项

  • 始终提供用户语言选项:使用 navigator.language 作为默认值,同时允许用户手动切换并存储到localStorage。
  • 回退策略:Intl构造函数接受一个语言数组作为 locales 参数,浏览器会按顺序选择第一个支持的语言。例如 [‘zh-TW’, ‘zh’, ‘en’]
  • 缓存 Intl 实例:反复创建相同的 Intl.NumberFormat 等实例会有微小开销。对于固定格式,可将其缓存复用。
  • 避免在服务端渲染中使用:Intl依赖浏览器环境,在Node.js中从IQ 16开始支持,但使用前需确保环境兼容性。
  • 检查支持情况:绝大多数现代浏览器均已完整支持Intl API,但若需兼容非常老旧的浏览器,可使用 Intl.js polyfill作为回退方案。

八、总结

JavaScript Intl API 提供了一整套功能强大且易于使用的国际化工具。通过本文的讲解,你已经掌握了数字、货币、日期、排序、列表连接、相对时间以及显示名称等核心能力。利用这些原生API,你可以放心地放弃庞大的第三方库,构建出轻量、高效、用户友好的多语言Web应用。

国际化不再是前端开发的难题,而是一次优雅的原生体验。立即在你的下一个项目中尝试使用Intl API,体验无依赖开发的畅快感受。

JavaScript Intl API 本地化实战:全面掌握数字货币日期与排序
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

版权声明:
本站资源有的来自互联网收集整理,本站纯免费分享提供学习使用,如果侵犯了您的合法权益,请联系本站我们会及时删除。
本站资源仅供研究、学习交流之用,免费开源项目不代表完全可商用,若商业用途请先咨询开发企业能否商用,否则产生的一切后果将由下载用户自行承担。
原创板块未经允许不得转载,否则将追究法律责任。

淘吗网 javascript JavaScript Intl API 本地化实战:全面掌握数字货币日期与排序 https://www.taomawang.com/web/javascript/2132.html

常见问题

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务