如何检查格式化器实际使用的 locale 和选项?
使用 resolvedOptions() 方法检查任意 Intl 格式化器的实际配置
简介
在 JavaScript 中创建 Intl 格式化器时,你请求的选项并不总是最终生效的选项。浏览器会进行 locale 协商、填充默认值,并规范化你的设置,生成最终的配置。resolvedOptions() 方法可以让你准确查看格式化器实际采用了哪些配置。
Intl API 中的每个格式化器都包含 resolvedOptions() 方法,包括 Intl.DateTimeFormat、Intl.NumberFormat、Intl.ListFormat、Intl.PluralRules、Intl.Collator 等。该方法会返回一个对象,包含格式化器在处理你的输入后最终采用的所有配置细节。
此方法主要用于调试、理解浏览器行为,以及检测当前环境下可用的功能。
基本语法
resolvedOptions() 方法不需要参数。你可以在任意格式化器实例上调用它,它会返回一个对象。
const formatter = new Intl.DateTimeFormat('en-US');
const options = formatter.resolvedOptions();
console.log(options);
// {
// locale: 'en-US',
// calendar: 'gregory',
// numberingSystem: 'latn',
// timeZone: 'America/Los_Angeles',
// ...
// }
返回的对象对于日期格式化器,至少包含 locale、calendar 和 numberingSystem 属性;对于数字格式化器,则至少包含 locale 和 numberingSystem。其他属性取决于你指定的选项以及格式化器类型支持的内容。
为什么请求的选项和解析后的选项会不同
请求的选项与解析后的选项可能不同,主要有三个原因。
首先,locale 协商会在你请求的 locale 不被支持时,选择最合适的可用 locale。例如,如果你请求 de-AT,但浏览器只支持 de,那么解析后的 locale 就会是 de。
const formatter = new Intl.DateTimeFormat('de-AT-u-ca-buddhist');
const options = formatter.resolvedOptions();
console.log(options.locale);
// Likely outputs: 'de-AT' or 'de'
console.log(options.calendar);
// Likely outputs: 'gregory' (if Buddhist calendar is not supported)
其次,浏览器会为您未指定的任何选项填充默认值。这些默认值是根据不同的本地化设置(locale)而定的。
const formatter = new Intl.NumberFormat('en-US');
const options = formatter.resolvedOptions();
console.log(options.style);
// Outputs: 'decimal'
console.log(options.minimumFractionDigits);
// Outputs: 0
console.log(options.maximumFractionDigits);
// Outputs: 3
第三,浏览器会将某些选项规范化为其标准形式。如果您使用 dateStyle 或 timeStyle,浏览器不会在解析后的选项中包含这些快捷方式,而是会包含它们展开后的各个组件选项。
检查实际使用的 locale
解析选项中的 locale 属性可以准确告诉您格式化器正在使用哪个 locale。这是 locale 协商的结果。
const formatter = new Intl.DateTimeFormat(['zh-TW', 'zh-CN', 'en-US']);
const options = formatter.resolvedOptions();
console.log(options.locale);
// Outputs the first supported locale from the list
如果您请求的 locale 包含 Unicode 扩展关键字,但这些关键字未被支持或被作为单独选项应用,则解析后的 locale 可能不会包含这些关键字。
const formatter = new Intl.NumberFormat('en-US-u-nu-arab');
const options = formatter.resolvedOptions();
console.log(options.locale);
// Might output: 'en-US'
console.log(options.numberingSystem);
// Might output: 'arab' or 'latn' depending on support
检查日期和时间格式化选项
对于 Intl.DateTimeFormat,解析后的选项会包含将显示哪些日期和时间组件以及显示方式的详细信息。
const formatter = new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
timeZone: 'America/New_York'
});
const options = formatter.resolvedOptions();
console.log(options.year);
// Outputs: 'numeric'
console.log(options.month);
// Outputs: 'long'
console.log(options.day);
// Outputs: 'numeric'
console.log(options.timeZone);
// Outputs: 'America/New_York'
console.log(options.calendar);
// Outputs: 'gregory'
当您使用 dateStyle 或 timeStyle 时,这些快捷方式不会包含在解析后的选项中。浏览器会根据 locale 将它们展开为各个组件选项。
const formatter = new Intl.DateTimeFormat('en-US', {
dateStyle: 'full'
});
const options = formatter.resolvedOptions();
console.log(options.dateStyle);
// Outputs: undefined
console.log(options.weekday);
// Outputs: 'long'
console.log(options.year);
// Outputs: 'numeric'
console.log(options.month);
// Outputs: 'long'
console.log(options.day);
// Outputs: 'numeric'
如果您创建一个没有任何选项的日期格式化器,解析后的选项会显示浏览器为该 locale 选择了哪些默认值。
const formatter = new Intl.DateTimeFormat('ja-JP');
const options = formatter.resolvedOptions();
console.log(options);
// Shows default date component options for Japanese locale
检查数字格式化选项
对于 Intl.NumberFormat,解析后的选项会告诉您样式、精度、分组以及其他格式化细节。
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
const options = formatter.resolvedOptions();
console.log(options.style);
// Outputs: 'currency'
console.log(options.currency);
// Outputs: 'USD'
console.log(options.currencyDisplay);
// Outputs: 'symbol'
console.log(options.minimumFractionDigits);
// Outputs: 2
console.log(options.maximumFractionDigits);
// Outputs: 2
您可以看到,即使只指定了货币,浏览器也会为 currencyDisplay 和小数位数填充默认值。
当你使用舍入选项时,resolved options 会精确显示数字将如何被舍入。
const formatter = new Intl.NumberFormat('en-US', {
minimumSignificantDigits: 3,
maximumSignificantDigits: 5
});
const options = formatter.resolvedOptions();
console.log(options.minimumSignificantDigits);
// Outputs: 3
console.log(options.maximumSignificantDigits);
// Outputs: 5
检查其他格式化器类型
resolvedOptions() 方法在所有 Intl 格式化器上工作方式相同。
对于 Intl.ListFormat,它会显示类型和样式。
const formatter = new Intl.ListFormat('en-US', {
style: 'long',
type: 'conjunction'
});
const options = formatter.resolvedOptions();
console.log(options.locale);
// Outputs: 'en-US'
console.log(options.style);
// Outputs: 'long'
console.log(options.type);
// Outputs: 'conjunction'
对于 Intl.PluralRules,它会显示类型以及最小/最大数字位数。
const formatter = new Intl.PluralRules('en-US', {
type: 'ordinal'
});
const options = formatter.resolvedOptions();
console.log(options.locale);
// Outputs: 'en-US'
console.log(options.type);
// Outputs: 'ordinal'
console.log(options.minimumIntegerDigits);
// Outputs: 1
resolvedOptions() 的常见用例
最常见的用例是调试。当格式化输出与预期不符时,resolvedOptions() 有助于你了解格式化器实际在做什么。
const formatter = new Intl.DateTimeFormat('en-US', {
dateStyle: 'medium'
});
console.log(formatter.format(new Date()));
// Check the output
console.log(formatter.resolvedOptions());
// See exactly which options produced that output
另一个用例是特性检测。你可以通过请求特定的日历、数字系统或其他特性,并查看实际解析结果,来判断是否支持。
const formatter = new Intl.DateTimeFormat('en-US', {
calendar: 'islamic'
});
const options = formatter.resolvedOptions();
if (options.calendar === 'islamic') {
console.log('Islamic calendar is supported');
} else {
console.log('Islamic calendar is not supported, using ' + options.calendar);
}
你还可以使用 resolvedOptions() 获取用户的本地化偏好。当你创建一个没有指定 locale 的格式化器时,浏览器会使用用户的偏好设置。
const formatter = new Intl.DateTimeFormat();
const options = formatter.resolvedOptions();
console.log(options.locale);
// Outputs: the user's preferred locale
console.log(options.timeZone);
// Outputs: the user's time zone
console.log(options.hourCycle);
// Outputs: the user's hour cycle preference (12 or 24 hour)
最后,你可以使用 resolved options 来重新创建一个完全相同的格式化器。返回的对象可以直接传递给构造函数。
const formatter1 = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
const options = formatter1.resolvedOptions();
const formatter2 = new Intl.NumberFormat(options.locale, options);
// formatter2 will format numbers identically to formatter1
关键要点
resolvedOptions() 方法返回一个包含格式化器实际配置的对象。由于本地化协商、默认值和标准化等原因,这些配置可能与你请求的不同。
每个 Intl 格式化器都有这个方法。你无需传递参数即可调用,并会收到一个包含 locale、calendar、numberingSystem 以及格式化器特定选项等属性的对象。
主要使用 resolvedOptions() 进行格式化器行为的调试、检测可用功能,以及了解浏览器如何解析你的选项。返回的对象还可以用于重新创建相同的格式化器或检查用户偏好设置。