JavaScript Intl 对象全面指南
Intl 对象是一个 JavaScript 的国际化 API,提供了精确的字符串对比、数字格式化和日期时间格式化功能。本文将全面介绍 Intl 对象的 API 功能和使用方法。
Intl 对象兼容性说明
Intl 对象不同于其他 ECMA 262 规范定义的 JS API,它是在 ECMA 402 中定义的。当我们查阅 ECMA 262 和 ECMA 402 规范可以发现它们之间的区别在于:
- ECMA 262:This Standard defines the ECMAScript xxx general-purpose programming language,本标准定义了 ECMAScript 通用编程语言规范;
- ECMA 402:This Standard defines the application programming interface for ECMAScript objects that support programs that need to adapt to the linguistic and cultural conventions used by different human languages and countries,本标准定义了 ECMAScript 对象的应用程序编程接口,这些对象支持需要适应不同人类语言和国家使用的语言和文化惯例的程序。
所以 ECMA-262 是 ECMAScript 语言规范(也就是我们熟知的 ES3、ES5、ES6…);而 ECMA-402 则是 JavaScript 的国际化 API 标准,专门定义一些关于国际化处理的 API 规范。
ECMA-402 规范最早在 2012 年 12 月分发布的第一个版本,到今天为止 ECMA-402 规范已经迭代了 12 次,从 2015 年(也就是 ES6)开始每年都会更新。
浏览器兼容上,从 2017 年 9 月(ES7)开始,市面上的主流浏览器都已经支持了 Intl 对象的使用。
下面我们再一起看下 Intl 对象的主要 API。
Intl.Locale
Intl.Locale
对象表示和操作 语言环境(locale) 信息,语言环境就是描述用户语言、地区和文化偏好的一个标识符,例如 en-US
代表说英语的美国。Intl.Locale
对象可以把这些字符串解析成结构化数据,并允许你提取、修改或扩展。
构造函数
使用 new Intl.Locale()
构造函数来创建一个 Intl.Locale
对象实例,该函数有两个参数:
-
tag
:必填参数,一个 Unicode BCP 47 规范的语言标签字符串或者一个Intl.Locale
对象;这个 Unicode BCP 47 语言标签由 5 个部分组成:language[-script][-region][-variants][-extensions]
- language:必填,例如
"en"
、"zh"
- script :可选,书写系统,例如
"Latn"
(拉丁字母)、"Hans"
(简体汉字) - region:可选,地区代码,例如
"US"
、"CN"
- variants / extensions:可选,用来指定特殊的扩展规则(比如日历、排序方式等)
- language:必填,例如
-
options
:一个区域设置的对象,用来指定或覆盖第一个参数的 Unicode 扩展关键字,包括:language
:语言子标签,由 23 或者 58 个字母组成,如en
、zh
等,全部数据在这个 XML 中维护;script
:书写格式,由 4 个字母组成,如Hans
,全部数据在这个 XML 中维护;region
:地区子标签,由 2~3 个字母组成,如"US"
,"CN"
,全部数据在这个 XML 中;variants
:一个连字符(-)分隔的唯一变体标签列表,其中每个标签都由 5~8 个字母数字或一个数字后跟 3 个字母数字组成,例如fonipa
表示国际音标,可以在这个 XML 中 查询;calendar
:历法,一个或多个由 3-8 个字母数字组成的段,由连字符连接,例如chinese
表示中国农历,可以在这个 XML 中查询;collation
:排序规则,例如pinyin
表示按照中文拼音顺序,可以在这个 XML 中查询;numberingSystem
:编号系统,例如arab
表示阿拉伯数字,可以在这个 XML 中查询;caseFirst
:大小写排序优先方式,可以设置为"upper"
、"lower"
、"false"
;hourCycle
:小时制格式,可以设置为"h23"
、"h12"
、"h11"
或实际上未使用的"h24"
;numeric
:是否按数字内容排序,true
或false
属性
Intl.Locale
对象具有以下属性,其中大部分属性和使用构造函数传递的第二个参数相关。
baseName
baseName
属性返回 BCP47 语言标签字符串,但是仅包括 language ["-" script] ["-" region] *("-" variant)
四个部分,不包含使用 -u
开头的扩展部分;
// Sets language to Japanese, region to Japan,
// calendar to Gregorian, hour cycle to 24 hours
const japan = new Intl.Locale("ja-JP-u-ca-gregory-hc-24");
console.log(japan.baseName); // "ja-JP"
- 其余属性和上面的
options
参数一致。
方法
getCalendars()
:返回多个历法字符串组成的数组。如果在创建Intl.Locale
对象时传递了calendar
,那么就直接返回;如果没有指定,则返回该 locale 下所有可用的历法;
const zh = new Intl.Locale("zh");
console.log(zh.getCalendars()); // ["gregory", "chinese"]
getCollations()
:返回多个排序规则字符串数组。
const locale = new Intl.Locale("zh");
console.log(locale.getCollations()); // ["pinyin", "stroke", "zhuyin", "emoji", "eor"]
getHourCycles()
:返回小时制字符串数组
console.log(new Intl.Locale("zh").getHourCycles()); // ["h23"]
getNumberingSystems()
:返回编号系统
const zh = new Intl.Locale("zh");
console.log(zh.getNumberingSystems()); // ["latn"]
getTextInfo()
:返回包含表示本地文本方向的direction
属性的对象
const zh = new Intl.Locale("zh");
console.log(zh.getTextInfo()); // { direction: "ltr" }
getTimeZones()
:返回时区字符串数组。如果创建Intl.Locale
对象时没有指定region
,那么会返回undefined
。
const zh = new Intl.Locale("zh");
console.log(zh.getTimeZones()); // undefined
const zh = new Intl.Locale("zh-CN");
console.log(zh.getTimeZones()); // ['Asia/Shanghai', 'Asia/Urumqi'] Asia/Urumqi是新疆乌鲁木齐时区
getWeekInfo()
:返回一个包含周信息的对象,包括firstDay
(一周的第一天是哪一天),weekend
(哪几天是周末),minimalDays
(表示月份或月份的第一周所需的最少天数)
const zh = new Intl.Locale("zh");
console.log(zh.getWeekInfo());
// {firstDay: 1, weekend: [6, 7]}
maximize()
:获取此语言环境的语言、文字和区域的最可能值组成的Intl.Locale
对象minimize()
:返回Intl.Locale
对象,该对象从区域语言标识符(本质上是 的内容)中删除所有语言、文字或地区子标签toString()
:返回完整的 Unicode BCP 47 区域设置标识符字符串,区别于baseName
属性
const zh = new Intl.Locale("zh-Hans-CN", { calendar: "chinese" });
console.log(zh.toString()); // zh-Hans-CN-u-ca-chinese
console.log(zh.baseName); // zh-Hans-CN
Intl.Collator
Collator
译为排序器,所以 Intl.Collator
对象用于语言敏感的字符串比较。
构造函数
使用 new Intl.Collator()
构造函数来创建一个 Intl.Collator
对象实例。值得注意的是,该构造函数不使用 new
就直接调用。
new Intl.Collator(locales, options);
// 或直接调用
Intl.Collator(locales, options);
构造函数有两个可选参数:
locales
: 语言标签字符串或Intl.Locale
对象,或者它们组成的数组;options
: 包含以下可选属性usage
:比较是否用于对字符串列表进行排序-"sort"
,或是否按键模糊过滤(对于拉丁字母,不区分变音符号和大小写)-"search"
;默认为排序;localeMatcher
:要使用的区域设置匹配算法,值可以是"lookup"
和"best fit"
,默认值为"best fit"
;collation
:特定语言环境的变体排序规则,同上;numeric
:是否应使用数字排序规则,比如 "1" < "2" < "10",true
或false
,默认false
;caseFirst
:是否先按大小写排序,可能的值为"upper"
、"lower"
和"false"
,默认false
;sensitivity
:设置字符串中的哪些差异影响排序结果,默认为"variant"
"base"
:忽略重音和大小写(a = á = A
)"accent"
:区分重音,忽略大小写(a ≠ á
,a = A
)"case"
:区分大小写,忽略重音(a = á
,a ≠ A
)"variant"
:区分所有差异,包括重音、大小写等(完全区分)
ignorePunctuation
:是否忽略标点,true
或false
;
方法
Intl.Collator
本身具有一个静态方法 Intl.Collator.supportedLocalesOf()
和两个实例方法 compare()
和 resolvedOptions()
。
supportedLocalesOf
参数:
locales
:必填,一个 Unicode BCP 47 规范的语言标签字符串或Intl.Locale
对象;或者它们任意一种的数组;options
:可选参数,一个对象,仅包含localeMatcher
属性localeMatcher
:可以设置为"lookup"
或"best fit"
;默认为"best fit"
,表示使用智能的近似匹配策略,"lookup"
则为严格匹配。
Intl.Collator.supportedLocalesOf(locales, options)
静态方法用来检测传入的语言环境中哪些是当前运行环境真正支持的。这个方法几乎在 Intl 的所有对象中都包含,主要用处有两个:
- 检测你传入的 locales 数组中的语言标签字符串是否都正确;
- 检测指定 Intl.xxx 对象是否在当前运行环境下支持所有你指定的语言环境下的国际化转换操作。
比如:
// 检查日期格式化器支持哪些 locale
console.log(
Intl.DateTimeFormat.supportedLocalesOf(["zh-CN", "en-GB", "fr-XX"])
);
// 返回: ["zh-CN", "en-GB"],也就是指定 fr-XX 写错了
compare
compare(string1, string2)
:按照指定语言的规则,比较两个字符串,返回一个数字。当 string1
排在 string2
前面时返回 -1
,反之则返回 1
;如果两个字符串相等,则返回 0
;
resolvedOptions
resolvedOptions()
:返回初始化 Intl.Collator
时计算的 options
对象,如果没有传递 options
,则返回 options
内部属性的默认值,例如英文字母比较规则如下
const de = new Intl.Collator("en");
de.resolvedOptions();
// 默认配置
caseFirst: "false";
collation: "default";
ignorePunctuation: false;
locale: "en";
numeric: false;
sensitivity: "variant";
usage: "sort";
Intl.DateTimeFormat
Intl.DateTimeFormat
对象用于日期时间格式化。
构造函数
使用 new Intl.DateTimeFormat(locales, options)
创建 Intl.DateTimeFormat
对象,也可以不使用 new
。
参数说明:
locales
:Unicode BCP 47 规范的语言标签字符串或Intl.Locale
对象,或者它们组成的数组;options
:localeMatcher
:要使用的区域设置匹配算法,值可以是"lookup"
和"best fit"
,默认值为"best fit"
;calendar
:历法,例如chinese
表示中国农历,可以使用Intl.supportedValuesOf("calendar")
方法获取所有历法枚举值;numberingSystem
:编号系统,例如arab
表示阿拉伯数字,可以使用Intl.supportedValuesOf("numberingSystem")
获取所有枚举值;hour12
:是否使用 12 小时制,true
或false
;hourCycle
:小时制格式,可以设置为"h23"
、"h12"
、"h11"
或"h24"
;timeZone
:使用的时区,例如Asia/Shanghai
;weekday
:星期几的表示形式"long"
:完整的日期名,例如 Monday、 Thursday;"short"
:日期缩写,例如 Mon、Thu;"narrow"
:最短日期名,例如 T(Tuesday)
era
:年代的表示"long"
:完整表示,例如 Anno Domini(基督纪元,公元);"short"
:缩写,例如 AD(Anno Domini);"narrow"
:最短表示,例如 A(Anno Domini)
year
:年份表示"numeric"
:实际数字"2-digit"
:两位数字
month
:月份表示"numeric"
:实际数字,例如 3(3 月份)"2-digit"
:两位数字,不够补 0,例如 03、12"long"
:完整表示,例如 March(三月份);"short"
:缩写,例如 Mar;"narrow"
:最短表示,例如 M
day
:日期表示"numeric"
:实际数字"2-digit"
:两位数字,不够补 0
dayPeriod
:日期时间段的格式"long"
:全称,例如 in the morning(早上);"short"
:缩写,例如 AM;"narrow"
:最短表示,例如 a
hour
:小时表示形式"numeric"
:实际数字"2-digit"
:两位数字,不够补 0
minute
:分钟表示"numeric"
:实际数字"2-digit"
:两位数字,不够补 0
second
:秒表示"numeric"
:实际数字"2-digit"
:两位数字,不够补 0
fractionalSecondDigits
:表示秒的小数部分的位数(多余的数字将被截断),可以是1
、2
、3
,最多 3 位;timeZoneName
:时区名称的本地化表示"long"
:全称,例如 Pacific Standard Time(太平洋时间);"short"
:缩写,例如 PST;"shortOffset"
:简短的本地化 GMT 格式,例如 GMT-8;"longOffset"
:长本地化 GMT 格式,例如 GMT-08:00;"shortGeneric"
:简短的通用非位置格式,例如 PT"longGeneric"
:长通用非位置格式,例如 Pacific Time
formatMatcher
:格式化算法,可以是"basic"
或"best fit"
;dateStyle
:要使用的日期格式化样式,可以是"full"
、"long"
、"medium"
和"short"
;timeStyle
:要使用的时间格式化样式,可以是"full"
、"long"
、"medium"
和"short"
;
方法
format(date)
format(date)
用于格式化日期。
参数:
date
:可以是一个Date
日期对象或者Temporal.PlainDateTime
对象,如果不传就是格式化当前本地时间;返回格式化后的字符串。例如获取当前本地时间:
返回值:
string
:格式化后的指定语言环境下的表示日期的字符串,结构取决于初始化Intl.DateTimeFormat
对象时的配置,例如格式化当前时间为本地语言可读的字符串
function getLocalDate() {
const now = new Date();
const formatter = new Intl.DateTimeFormat(navigator.language, {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
weekday: "long",
});
// 格式化当前日期和时间
return formatter.format(now);
}
// 'YYYY年M月D日星期W HH:mm:ss'
获取指定秒时间戳的可读字符串:
function formatTimestamp(seconds) {
const date = new Date(seconds * 1000); // 秒转毫秒
const formatter = new Intl.DateTimeFormat("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false, // 24小时制
});
return formatter.format(date);
}
formatTimestamp(1704038400); // '2024/01/01 00:00:00'
formatToParts(date)
formatToParts(date)
返回 Intl.DateTimeFormat
的一个对象数组,该数组包含所返回的格式化字符串的各个部分,对于根据特定语言环境的标记构建自定义字符串非常有用,比如构建 YYYY-MM-DD HH:mm:ss
等格式的字符串可以使用以下方式:
const date = new Date("2025-09-04T08:05:09");
// 创建格式化器
const formatter = new Intl.DateTimeFormat("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false, // 24 小时制
});
// 格式化
const parts = formatter.formatToParts(date);
const map = {};
for (const part of parts) {
map[part.type] = part.value;
}
// YYYY-MM-DD HH:mm:ss
const formattedDash = `${map.year}-${map.month}-${map.day} ${map.hour}:${map.minute}:${map.second}`;
formatRange()
formatRange(startDate, endDate)
用于格式化日期范围,返回给定日期范围的字符串。
formatRangeToParts()
formatRangeToParts(startDate, endDate)
返回 Intl.DateTimeFormat
的一个对象数组,该数组包含所返回的格式化字符串的各个部分。
resolvedOptions()
计算 Intl.DateTimeFormat 对象的配置。
const region = new Intl.DateTimeFormat("zh-CN");
region.resolvedOptions();
calendar: "gregory";
day: "numeric";
locale: "zh-CN";
month: "numeric";
numberingSystem: "latn";
timeZone: "Asia/Shanghai";
year: "numeric";
Intl.DurationFormat
Intl.DurationFormat
对象用于格式化时间间隔。
Intl.DurationFormat
是 ES2025 新加入的 API,仅在较新的浏览器版本中支持,比如 chrome > 129
构造函数
使用 new Intl.DurationFormat(locales, options)
创建 Intl.DurationFormat
对象,该函数接收两个可选参数:
locales
:Unicode BCP 47 规范的语言标签字符串或Intl.Locale
对象,或者它们各自组成的数组;options
:localeMatcher
:要使用的区域设置匹配算法,值可以是"lookup"
和"best fit"
,默认值为"best fit"
;numberingSystem
:编号系统,例如arab
表示阿拉伯数字,可以使用Intl.supportedValuesOf("numberingSystem")
查看所有枚举值;style
:格式化时长的样式,默认值为"short"
"long"
:全称,例如 1 hour and 50 minutes;"short"
:缩写,例如 1 hr, 50 min;"narrow"
:最短表示,例如 1h 50m;"digital"
:仅使用数字表示,例如 1:50:00
years
:年份格式,可以是"long"
、"short"
或"narrow"
,默认为style
设置的值,没有则为"short"
;yearsDisplay
:是否总是显示有几年,可以是"always"
或"auto"
,默认为"auto"
;如果指定了years
,则会始终展示;months
:月份格式,以下均同上;monthsDisplay
:是否总显示有几个月;weeks
:周格式;weeksDisplay
:是否总显示有几周;days
:日格式;daysDisplay
:是否总显示有几天;hours
:时间格式,可以是"long"
、"short"
、"narrow"
、"numeric"
或"2-digit"
;hoursDisplay
:是否总显示有几小时;minutes
:分钟格式;minutesDisplay
:是否总显示有几分钟;seconds
:秒格式;secondsDisplay
:是否总显示有几秒;milliseconds
:毫秒格式;millisecondsDisplay
:是否总显示毫秒;microseconds
:微秒格式;microsecondsDisplay
:是否显示微秒;nanoseconds
:纳秒格式;nanosecondsDisplay
:是否显示纳秒;fractionalSecondDigits
:表示秒的小数部分的位数(多余的数字将被截断),可能的值是从 0 到 9
方法
Intl.DurationFormat
包含一个静态方法和三个实例方法:
supportedLocalesOf
Intl.DurationFormat.supportedLocalesOf
静态方法同上述的 Intl.Collator.supportedLocalesOf
format
format(duration)
方法用来格式化时间间隔。
参数:
duration
:必填,一个对象,可包含以下属性,每个属性值必须是正整数;或者也可以是一个Temporal.Duration
对象years
: 年months
: 月weeks
: 周days
: 日hours
: 时minutes
: 分seconds
: 秒milliseconds
: 毫秒microseconds
: 微秒nanoseconds
: 纳秒
返回值:
string
:返回格式化后的时间间隔字符串,字符串的结构取决于初始化Intl.DurationFormat
对象时的配置。
formatToParts
formatToParts(duration)
将时间间隔转换成每一部分时间组成的对象数组。
参数同上,返回一个包含 type
、 value
或 unit
的对象数组,示例:
const duration = {
hours: 7,
minutes: 8,
seconds: 9,
milliseconds: 123,
microseconds: 456,
nanoseconds: 789,
};
new Intl.DurationFormat("en", { style: "long" }).formatToParts(duration);
// Returned value:
[
{ type: "integer", value: "7", unit: "hour" },
{ type: "literal", value: " ", unit: "hour" },
{ type: "unit", value: "hours", unit: "hour" },
{ type: "literal", value: ", " },
{ type: "integer", value: "8", unit: "minute" },
{ type: "literal", value: " ", unit: "minute" },
{ type: "unit", value: "minutes", unit: "minute" },
{ type: "literal", value: ", " },
{ type: "integer", value: "9", unit: "second" },
{ type: "literal", value: " ", unit: "second" },
{ type: "unit", value: "seconds", unit: "second" },
{ type: "literal", value: ", " },
{ type: "integer", value: "123", unit: "millisecond" },
{ type: "literal", value: " ", unit: "millisecond" },
{ type: "unit", value: "milliseconds", unit: "millisecond" },
{ type: "literal", value: ", " },
{ type: "integer", value: "456", unit: "microsecond" },
{ type: "literal", value: " ", unit: "microsecond" },
{ type: "unit", value: "microseconds", unit: "microsecond" },
{ type: "literal", value: ", " },
{ type: "integer", value: "789", unit: "nanosecond" },
{ type: "literal", value: " ", unit: "nanosecond" },
{ type: "unit", value: "nanoseconds", unit: "nanosecond" },
];
resolvedOptions
resolvedOptions()
方法获取初始化 Intl.DurationFormat
对象的配置对象,属性同 Intl.DurationFormat
构造函数的 options
。
Intl.RelativeTimeFormat
Intl.RelativeTimeFormat
对象用于格式化相对时间(如"3 天前"、"2 个月后"等),实现语言敏感的相对时间格式化。
构造函数
使用 new Intl.RelativeTimeFormat(locales, options)
创建 Intl.RelativeTimeFormat
对象,该函数接收两个可选参数:
locales
:Unicode BCP 47 规范的语言标签字符串或Intl.Locale
对象,或者它们各自组成的数组;options
:localeMatcher
:要使用的区域设置匹配算法,值可以是"lookup"
和"best fit"
,默认值为"best fit"
;numberingSystem
:编号系统,例如"arab"
表示阿拉伯数字,可以使用Intl.supportedValuesOf("numberingSystem")
查看所有枚举值;style
:消息的格式化样式,默认值为"long"
"long"
:完整样式,例如 "in 1 month";"short"
:缩写样式,例如 "in 1 mo.";"narrow"
:最短样式,例如 "in 1 mo";
numeric
:数字格式控制,默认值为"always"
"always"
:总是使用数字格式,例如 "1 day ago";"auto"
:自动选择,当可能时使用更自然的表达,例如 "yesterday";
方法
Intl.RelativeTimeFormat
包含一个静态方法和三个实例方法:
supportedLocalesOf
Intl.RelativeTimeFormat.supportedLocalesOf(locales, options)
静态方法返回提供的区域设置中支持的区域设置数组,无需使用运行时的默认区域设置。
format
format(value, unit)
方法用来将指定间隔的时间格式化,注意这个相对不是相对于当前时间,它只是简单地把你给的数字 + 单位变成合适的相对时间描述。
参数:
value
:必填,数字,表示相对时间的数值,其含义取决于设置的unit
,比如unit
为"day"
,如果value
为正数,表示几天前;如果value
为负数,则表示几天后;unit
:必填,字符串,表示时间单位,可选值为:"year"
或"years"
:年"quarter"
或"quarters"
:季度"month"
或"months"
:月"week"
或"weeks"
:周"day"
或"days"
:日"hour"
或"hours"
:小时"minute"
或"minutes"
:分钟"second"
或"seconds"
:秒
返回值:
string
:返回格式化后的相对时间字符串。
const rtf = new Intl.RelativeTimeFormat("zh-CN", { numeric: "auto" });
console.log(rtf.format(-1, "day")); // 昨天
console.log(rtf.format(0, "day")); // 今天
console.log(rtf.format(1, "day")); // 明天
console.log(rtf.format(-1, "week")); // 上周
const rtfNumeric = new Intl.RelativeTimeFormat("zh-CN", { numeric: "always" });
console.log(rtfNumeric.format(-1, "day")); // 1天前
formatToParts
formatToParts(value, unit)
将相对时间转换成每一部分组成的对象数组。
参数同上,返回一个包含 type
和 value
的对象数组:
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
rtf.formatToParts(-1, "day");
// [
// { type: 'literal', value: 'yesterday' }
// ]
rtf.formatToParts(1, "day");
// [
// { type: 'literal', value: 'tomorrow' }
// ]
const rtfNumeric = new Intl.RelativeTimeFormat("en", { numeric: "always" });
rtfNumeric.formatToParts(-1, "day");
// [
// { type: 'integer', value: '1' },
// { type: 'literal', value: ' day ago' }
// ]
resolvedOptions
resolvedOptions()
方法获取初始化 Intl.RelativeTimeFormat
对象的配置对象,属性同 Intl.RelativeTimeFormat
构造函数的 options
。
Intl.NumberFormat
Intl.NumberFormat
对象用于对数字进行格式化转换,包括小数、百分比、货币以及单位等多种样式。
构造函数
使用 new Intl.NumberFormat(locales, options)
创建 Intl.NumberFormat
对象,可以不使用 new
而直接调用,该函数接收两个可选参数:
locales
:Unicode BCP 47 语言标签字符串、Intl.Locale
对象,或它们各自组成的数组;options
:localeMatcher
:区域设置匹配算法,"lookup"
或"best fit"
,默认"best fit"
;numberingSystem
:编号系统,例如"latn"
、"arab"
等;style
:格式化样式,默认"decimal"
"decimal"
:十进制数字(默认);"percent"
:百分比(输入 0.5 => 输出 50%);"currency"
:货币格式(需配合currency
);"unit"
:单位格式(需配合unit
);
currency
:ISO 4217 货币代码(如"CNY"
、"USD"
、"CNY"
),当style
为"currency"
时必填;currencyDisplay
:货币的显示形式"symbol"
:默认值,表示使用本地化货币标识符,例如人民币是 ¥;"code"
:表示使用 ISO 4217 货币代码;"narrowSymbol"
:表示使用货币标识+数值,例如 $100;"name"
:使用货币名称,例如人民币是人民币
,美元则是"dollar"
;
currencySign
:会计记号"standard"
:默认值,使用常规的货币符号格式;"accounting"
:在负数金额时,会用会计记账常用的 括号 来表示,而不是负号,例如 ($1,234.00),这在一些公司的财报中比较常见
unit
:单位(如"kilometer"
、"celsius"
、"byte"
、"kilometer-per-hour"
),当style
为"unit"
时必填;unitDisplay
:单位显示形式"long"
:在数值和单位之间使用空格,且单位为完整名称,例如 16 litres(16 升);- ``"short"`:默认值,在数值和单位之间使用空格,例如 16 l;
"narrow"
:在数值和单位之间不使用空格,例如 16l;
notation
:记数法"standard"
:普通数字格式,例如 "1,234,567";"scientific"
:科学计数法;"engineering"
:工程计数法,指数是 3 的倍数;"compact"
:紧凑记法(缩写),常用于显示大数,例如 1.2M(million)
compactDisplay
:紧凑记数法的显示样式,"short"
或"long"
(仅当notation: "compact"
时有效);useGrouping
:是否显示分组分隔符,例如千分位逗号分隔"always"
:总是显示;"auto"
:默认值,根据当前语言环境选择是否显示;"min2"
:当组中至少有2位数字时,显示分组分隔符;true
或false
:显示或不显示
signDisplay
:是否显示数字的正负号"auto"
:默认值,只在负数时显示,包括 -0;"always"
:总是显示;"exceptZero"
:除了 0 正负数字的符号都显示;"negative"
:只在负数显示;"never"
:不显示
minimumIntegerDigits
:最少整数位数,可以设置为1~21
,默认为1
;在格式化时,小于此数字的整数位数的值将在左侧填充 0;minimumFractionDigits
、maximumFractionDigits
:最少/最多小数位数,可以设置为0~100
;普通数字和百分比格式的默认值为0
;货币格式的默认值是 ISO 4217 货币代码列表提供的值;minimumSignificantDigits
、maximumSignificantDigits
:最少/最多有效数字位数,可以设置为1~21
,默认为1
;roundingMode
:舍入模式,"ceil"
、"floor"
、"expand"
、"trunc"
、"halfCeil"
、"halfFloor"
、"halfExpand"
、"halfTrunc"
、"halfEven"
;roundingPriority
:"auto"
、"morePrecision"
、"lessPrecision"
;roundingIncrement
:相对于计算出的舍入幅度应进行舍入的增量,允许值如 1、2、5、10、20、25、50、100、200、250、500、1000、2000、2500、5000,默认值为 1;trailingZeroDisplay
:在整数上显示尾随零的方式"auto"
:根据minimumFractionDigits
和minimumSignificantDigits
保持尾随零;"stripIfInteger"
:如果分数数字全部为零,则删除分数数字。
方法
Intl.NumberFormat
提供一个静态方法以及多个实例方法:
supportedLocalesOf
同上
format
format(number)
将数字格式化为字符串。
参数:
number
:可以是 Number、BigInt 或字符串
返回指定语言环境下的字符串,示例:
- 基础十进制格式化
const nf = new Intl.NumberFormat("zh-CN");
console.log(nf.format(1234567.89)); // 1,234,567.89
- 百分比
const percent = new Intl.NumberFormat("en", {
style: "percent",
maximumFractionDigits: 1,
});
console.log(percent.format(0.756)); // 75.6%
- 货币
const cny = new Intl.NumberFormat("zh-CN", {
style: "currency",
currency: "CNY",
});
console.log(cny.format(1234.5)); // ¥1,234.50
const usdAccounting = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
currencySign: "accounting",
});
console.log(usdAccounting.format(-1234.5)); // ($1,234.50)
- 单位
const speed = new Intl.NumberFormat("en", {
style: "unit",
unit: "kilometer-per-hour",
unitDisplay: "short",
});
console.log(speed.format(88)); // 88 km/h
- 紧凑记数法
const compact = new Intl.NumberFormat("en", {
notation: "compact",
compactDisplay: "short",
});
console.log(compact.format(12345)); // 12K
formatToParts
formatToParts(number)
将格式化结果拆分为各部分的对象数组,包括以下属性:
-
type
:类型 -
value
:值字符串
const cny = new Intl.NumberFormat("zh-CN", {
style: "currency",
currency: "CNY",
});
console.log(cny.formatToParts(1234.5));
[
{
"type": "currency",
"value": "¥"
},
{
"type": "integer",
"value": "1"
},
{
"type": "group",
"value": ","
},
{
"type": "integer",
"value": "234"
},
{
"type": "decimal",
"value": "."
},
{
"type": "fraction",
"value": "50"
}
]
formatRange
formatRange(start, end)
用于格式化数字区间(如 3–5 个单位),返回格式化的字符串。
const nf = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "CNY",
});
console.log(nf.formatRange(3, 5)); // CN¥3.00–5.00
formatRangeToParts
formatRangeToParts(start, end)
返回数字区间的分段信息,其中 type
和 value
同 formatToParts
,source
属性用来去分当前分段的来源是属于传入的 start
还是 end
参数的部分,值可以是以下三种:
startRange
:当前分段属于参数start
的;endRange
:当前分段属于参数end
;shared
:共享部分;例如,货币符号、“-” 分隔符等
const nf = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "CNY",
});
console.log(nf.formatRange(3, 5));
[
{
"type": "currency",
"value": "CN¥",
"source": "shared"
},
{
"type": "integer",
"value": "3",
"source": "startRange"
},
{
"type": "literal",
"value": "–",
"source": "shared"
},
{
"type": "integer",
"value": "5",
"source": "endRange"
}
]
resolvedOptions
resolvedOptions()
返回初始化对象时解析得到的配置对象,其属性同初始化对象时传入的配置保持一致。
浏览器兼容性
现代主流浏览器与 Node.js 均已广泛支持 Intl.NumberFormat
的核心能力;部分较新的选项(如 roundingMode
、trailingZeroDisplay
等)在旧版本环境中可能不受支持,建议参考 MDN 兼容性表并按需做回退与检测。
Intl.ListFormat
Intl.ListFormat
是一个语言相关的列表格式化构造器,用于以给定语言环境的习惯将字符串数组格式化为自然语言列表。
构造函数
使用 new Intl.ListFormat(locales, options)
创建 Intl.ListFormat
对象:
locales
:Unicode BCP 47 语言标签字符串、Intl.Locale
对象,或它们各自组成的数组;options
:localeMatcher
:区域设置匹配算法,"lookup"
或"best fit"
;type
:列表类型,默认"conjunction"
"conjunction"
:合并(和)列表,如 "A, B, and C";"disjunction"
:析取(或)列表,如 "A, B, or C";"unit"
:单位值的列表,如 "5 pounds, 12 ounces";
style
:风格,默认"long"
"long"
:长格式;"short"
:短格式;"narrow"
:最窄格式(当style
为"narrow"
时,type
只能为"unit"
)。
方法
supportedLocalesOf
Intl.ListFormat.supportedLocalesOf(locales, options)
返回受支持的区域设置列表。
format
format(list)
将多个字符串组合在一起格式化为指定的语言列表。
参数:
list
:一个可迭代的对象,例如字符串数组。
返回组合后的字符串。
const list = ["Motorcycle", "Bus", "Car"];
console.log(
new Intl.ListFormat("en-GB", { style: "long", type: "conjunction" }).format(
list,
),
);
// Motorcycle, Bus and Car
console.log(
new Intl.ListFormat("en-GB", { style: "short", type: "disjunction" }).format(
list,
),
);
// Motorcycle, Bus or Car
console.log(
new Intl.ListFormat("en-GB", { style: "narrow", type: "unit" }).format(list),
);
// Motorcycle Bus Car
formatToParts
formatToParts(list: string[])
返回组成该列表的分段对象数组,包含类型与值。
const fruits = ["Apple", "Orange", "Pineapple"];
const myListFormat = new Intl.ListFormat("en-GB", {
style: "long",
type: "conjunction",
});
console.table(myListFormat.formatToParts(fruits));
[
{ "type": "element", "value": "Apple" },
{ "type": "literal", "value": ", " },
{ "type": "element", "value": "Orange" },
{ "type": "literal", "value": " and " },
{ "type": "element", "value": "Pineapple" }
]
resolvedOptions
resolvedOptions()
返回初始化对象时解析得到的配置对象,其属性同初始化对象时传入的配置保持一致。
浏览器兼容性
现代浏览器已支持 Intl.ListFormat
。如果需要在不支持的环境中使用,可采用 polyfill(例如 FormatJS 提供的 polyfill)。
Intl.PluralRules
Plural
译为复数,Intl.PluralRules
对象用于按照特定语言的复数规则对数值进行分类(如 one、few、many 等)。
不同的语言使用不同的形式来表示事物的复数(基数)和事物的顺序(序数)。例如英语区分单数和复数的常用形式是在事物单名词后加一个字母 s
(有些不可数名词不加);中文则只有一种,无论是一个还是多个都不会对名词进行修改;还有英语用四种表示顺序的形势:"th", "st", "nd", "rd", 而中文和阿拉伯语都只有一种表达序数的形式。
构造函数
使用 new Intl.PluralRules(locales, options)
创建 Intl.PluralRules
对象:
locales
:Unicode BCP 47 语言标签字符串、Intl.Locale
对象,或它们各自组成的数组;options
:localeMatcher
:区域设置匹配算法,"lookup"
或"best fit"
;type
:复数类别类型,默认"cardinal"
"cardinal"
:基数复数规则(0, 1, 2, ...);"ordinal"
:序数复数规则(第一、第二、第三等,或者 "1st", "2nd", "3rd");
minimumIntegerDigits
、minimumFractionDigits
、maximumFractionDigits
、minimumSignificantDigits
、maximumSignificantDigits
、roundingPriority
、roundingIncrement
、roundingMode
:同Intl.NumberFormat
对象的参数,用来控制数值格式化时的精度,影响分类结果(可选)。
方法
supportedLocalesOf
Intl.PluralRules.supportedLocalesOf(locales, options)
静态方法返回受支持的区域设置。
select
select(number)
返回传入数字的指定语言环境下的复数类别字符串,返回值只会是这几种:zero
、one
、 two
、 few
、 many
、或 other
。如果一个语言的没有单复数区别形式,例如中文,那么只会返回 other
。不同语言的返回值可以参考 LDML 语言负数规则定义表。
// 阿拉伯语有更丰富的复数类别
const prAr = new Intl.PluralRules("ar-EG");
console.log(prAr.select(0)); // 'zero'
console.log(prAr.select(1)); // 'one'
console.log(prAr.select(2)); // 'two'
console.log(prAr.select(6)); // 'few'
console.log(prAr.select(18)); // 'many'
// 中文则只会返回 other
const zh = new Intl.PluralRules("zh-CN");
console.log(prAr.select(0)); // 'other'
console.log(prAr.select(1)); // 'other'
console.log(prAr.select(2)); // 'other'
console.log(prAr.select(6)); // 'other'
console.log(prAr.select(18)); // 'other'
通用的格式化文本段落中复数格式的方法:
// 在消息格式化中使用
function formatItems(count: number, lang = "en") {
const pr = new Intl.PluralRules(lang);
const rules: Record<string, string> = {
one: `${count} item`,
other: `${count} items`,
};
return rules[pr.select(count)] ?? rules.other;
}
selectRange
selectRange(start, end)
对数值范围进行分类,返回 zero
、one
、 two
、 few
、 many
、或 other
。
new Intl.PluralRules("sl").selectRange(102, 201); // 'few'
new Intl.PluralRules("pt").selectRange(102, 102); // 'other'
resolvedOptions
resolvedOptions()
返回初始化对象时解析得到的选项。
浏览器兼容性
现代浏览器已支持 Intl.PluralRules
的核心功能。不同语言的可用类别由运行时的 CLDR 数据决定;如需在旧环境中使用,可参考社区 polyfill(如 FormatJS)。
Intl.Segmenter
Intl.Segmenter
对象用于将指定语言环境下字符串拆分为词、字或句级别的有意义片段。
Intl.Segmenter
对象是 ES 2024 新加入的 API,目前仅在较新版本浏览器中支持,例如 chrome > 87
构造函数
使用 new Intl.Segmenter(locales, options)
创建 Intl.Segmenter
对象:
locales
:Unicode BCP 47 语言标签字符串、Intl.Locale
对象,或它们各自组成的数组;options
:localeMatcher
:区域设置匹配算法,"lookup"
或"best fit"
;granularity
:拆分粒度,必填,取值:"grapheme"
:按照 grapheme 集群(在计算机和语言学里,grapheme 指的是人类直观上认为的一个字符,而不是底层存储的码点或字节)边界将输入分割成段"word"
:根据语言环境的决定,在单词边界处将输入分割成段。"sentence"
:根据语言环境的决定,在句子边界处将输入分割成段。
方法
supportedLocalesOf
Intl.Segmenter.supportedLocalesOf(locales, options)
返回受支持的区域设置。
segment
segment(input: string)
根据当前设置对文本进行分段,返回 Segments
可迭代对象(可以使用 for…of
遍历或者使用 …
转换成数组)。
Segments
迭代器的对象属性如下:
segment
:该片段的字符串值;index
:该片段在原始输入中的起始索引;input
:原始输入字符串;isWordLike
:当granularity
为"word"
时,指示该分段是否是类词的标记(如字母数字词)。
const segmenter = new Intl.Segmenter("zh-CN", { granularity: "word" });
const text = "今天天气很好。我打算去公园散步,然后喝杯咖啡。";
// 使用 segment 方法
const segments = segmenter.segment(text);
// segment 返回一个可迭代对象,可以遍历
for (const { segment, index, isWordLike } of segments) {
console.log({ segment, index, isWordLike });
}
{segment: '今天', index: 0, isWordLike: true}
{segment: '天气', index: 2, isWordLike: true}
{segment: '很好', index: 4, isWordLike: true}
{segment: '。', index: 6, isWordLike: false}
{segment: '我', index: 7, isWordLike: true}
{segment: '打算', index: 8, isWordLike: true}
{segment: '去', index: 10, isWordLike: true}
{segment: '公园', index: 11, isWordLike: true}
{segment: '散步', index: 13, isWordLike: true}
{segment: ',', index: 15, isWordLike: false}
{segment: '然后', index: 16, isWordLike: true}
{segment: '喝杯', index: 18, isWordLike: true}
{segment: '咖啡', index: 20, isWordLike: true}
{segment: '。', index: 22, isWordLike: false}
resolvedOptions
resolvedOptions()
返回初始化时解析得到的选项。
总结
Intl 对象为 JavaScript 提供了强大的国际化能力,使得开发多语言应用变得更加简单和规范。通过合理使用 Intl 提供的各种格式化器,可以确保应用在不同语言环境下的正确显示和用户体验。