如何获取支持的日历、货币和时区列表
了解您的 JavaScript 环境支持哪些国际化值
介绍
在构建国际化应用程序时,您经常需要创建用户界面元素,例如下拉菜单、选择器或表单,让用户选择日历、货币、时区或其他本地化选项。为了构建这些组件,您需要知道 JavaScript 环境支持哪些值。
与其维护可能过时或包含浏览器不支持值的硬编码列表,不如使用 JavaScript 提供的方法在运行时发现支持的值。这可以确保您的应用程序仅提供在用户环境中能正确运行的选项。
Intl.supportedValuesOf() 方法返回支持的国际化值列表。您可以通过查询此方法获取 JavaScript 环境支持的日历、货币、时区、数字系统、排序类型和测量单位。
Intl.supportedValuesOf 返回的内容
Intl.supportedValuesOf() 方法接受一个字符串参数,用于指定返回哪种类型的值。它返回一个字符串数组,表示该类型支持的值。
const calendars = Intl.supportedValuesOf("calendar");
console.log(calendars);
// 输出: ["buddhist", "chinese", "coptic", "dangi", ...]
该方法支持六种不同的键类型:
"calendar"返回支持的日历系统"currency"返回支持的货币代码"timeZone"返回支持的时区标识符"numberingSystem"返回支持的数字系统"collation"返回支持的排序类型"unit"返回支持的测量单位
返回的数组始终按字母升序排序,不包含重复值,并使用符合 Unicode 标准的规范标识符。
如果传递了无效的键,该方法会抛出一个 RangeError:
try {
Intl.supportedValuesOf("invalid");
} catch (error) {
console.error(error.name);
// 输出: "RangeError"
}
此错误表明您使用了该方法无法识别的键。
获取支持的日历
日历系统定义了日期的计算和显示方式。不同的文化使用不同的日历系统,JavaScript 通过 Intl API 支持许多这些系统。
"calendar" 键返回 JavaScript 环境支持的所有日历系统:
const calendars = Intl.supportedValuesOf("calendar");
console.log(calendars);
// 输出: ["buddhist", "chinese", "coptic", "dangi", "ethioaa",
// "ethiopic", "gregory", "hebrew", "indian", "islamic",
// "islamic-civil", "islamic-rgsa", "islamic-tbla",
// "islamic-umalqura", "iso8601", "japanese", "persian",
// "roc"]
最常见的日历是 "gregory",它表示世界大部分地区使用的公历。其他日历包括:
"buddhist"表示泰国佛教日历"chinese"表示传统的中国农历"islamic"表示伊斯兰教的回历"hebrew"表示希伯来日历"japanese"表示带有年号的日本日历
每种日历都会影响日期的格式化和计算方式。当您使用带有特定日历的 Intl.DateTimeFormat 时,日期会根据该日历的规则显示:
const date = new Date("2025-10-15");
const gregorianFormat = new Intl.DateTimeFormat("en-US", {
calendar: "gregory",
year: "numeric",
month: "long",
day: "numeric"
});
const islamicFormat = new Intl.DateTimeFormat("en-US", {
calendar: "islamic",
year: "numeric",
month: "long",
day: "numeric"
});
console.log(gregorianFormat.format(date));
// 输出: "October 15, 2025"
console.log(islamicFormat.format(date));
// 输出: "Rabi' II 13, 1447 AH"
同一个 JavaScript 日期在使用不同日历格式化时会显示不同的结果。
使用支持的日历构建选择器
在用户界面中构建日历选择器时,可以查询支持的日历并为每个日历创建选项:
const calendars = Intl.supportedValuesOf("calendar");
const select = document.createElement("select");
calendars.forEach(calendar => {
const option = document.createElement("option");
option.value = calendar;
option.textContent = calendar;
select.appendChild(option);
});
document.body.appendChild(select);
这将创建一个下拉菜单,其中仅包含当前环境中可用的日历。
您可以通过使用 Intl.DisplayNames 来显示人类可读的日历名称,从而增强此选择器:
const calendars = Intl.supportedValuesOf("calendar");
const displayNames = new Intl.DisplayNames(["en-US"], { type: "calendar" });
calendars.forEach(calendar => {
const option = document.createElement("option");
option.value = calendar;
option.textContent = displayNames.of(calendar);
// 创建诸如 "Gregorian Calendar"、"Islamic Calendar" 等选项。
});
这将显示描述性名称,而不是技术标识符。
获取支持的货币
货币代码用于标识全球范围内使用的货币系统。JavaScript 支持基于 ISO 4217 标准的数百种货币代码。
"currency" 键返回 JavaScript 环境支持的所有货币代码:
const currencies = Intl.supportedValuesOf("currency");
console.log(currencies.length);
// 输出:通常超过 300
console.log(currencies.slice(0, 10));
// 输出:["ADP", "AED", "AFA", "AFN", "ALK", "ALL", "AMD", "ANG", "AOA", "AOK"]
货币代码由三个大写字母组成。常见示例包括:
"USD"表示美元"EUR"表示欧元"GBP"表示英镑"JPY"表示日元"CNY"表示人民币
该列表包括当前流通的货币以及一些已停止流通的历史货币。
在格式化货币值时,您必须指定使用哪种货币:
const amount = 1234.56;
const usdFormat = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
const eurFormat = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "EUR"
});
console.log(usdFormat.format(amount));
// 输出:"$1,234.56"
console.log(eurFormat.format(amount));
// 输出:"€1,234.56"
货币代码决定了显示的符号以及值的格式。
为用户选择过滤货币
大多数应用程序只需要显示当前常用的货币。您可以过滤支持的货币列表,仅包含对您的用户相关的货币:
const allCurrencies = Intl.supportedValuesOf("currency");
const commonCurrencies = ["USD", "EUR", "GBP", "JPY", "CNY", "INR", "CAD", "AUD"];
const availableCurrencies = commonCurrencies.filter(currency =>
allCurrencies.includes(currency)
);
console.log(availableCurrencies);
// 输出:["USD", "EUR", "GBP", "JPY", "CNY", "INR", "CAD", "AUD"]
这可以确保您只提供既满足需求又受浏览器支持的货币。
显示货币名称
在构建货币选择器时,显示描述性名称而不是三字母代码:
const currencies = ["USD", "EUR", "GBP", "JPY"];
const displayNames = new Intl.DisplayNames(["en-US"], { type: "currency" });
currencies.forEach(currency => {
const name = displayNames.of(currency);
console.log(`${currency}: ${name}`);
});
// 输出:
// USD: US Dollar
// EUR: Euro
// GBP: British Pound
// JPY: Japanese Yen
通过显示每个代码所代表的内容,可以提供更好的用户体验。
获取支持的时区
时区表示观察相同标准时间的地理区域。JavaScript 支持基于 IANA 时区数据库的数百个时区标识符。
"timeZone" 键返回 JavaScript 环境支持的所有时区标识符:
const timeZones = Intl.supportedValuesOf("timeZone");
console.log(timeZones.length);
// 输出:通常超过 400
console.log(timeZones.slice(0, 10));
// 输出:["Africa/Abidjan", "Africa/Accra", "Africa/Addis_Ababa",
// "Africa/Algiers", "Africa/Asmara", "Africa/Bamako",
// "Africa/Bangui", "Africa/Banjul", "Africa/Bissau", "Africa/Blantyre"]
时区标识符遵循 Continent/City 格式,例如 "America/New_York" 或 "Europe/London"。某些标识符包含额外的组件,例如 "America/Indiana/Indianapolis"。
在格式化日期和时间时,时区会影响显示的本地时间:
const date = new Date("2025-10-15T12:00:00Z");
const newYorkFormat = new Intl.DateTimeFormat("en-US", {
timeZone: "America/New_York",
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
timeZoneName: "short"
});
const tokyoFormat = new Intl.DateTimeFormat("en-US", {
timeZone: "Asia/Tokyo",
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric",
timeZoneName: "short"
});
console.log(newYorkFormat.format(date));
// 输出:"2025年10月15日 上午8:00 EDT"
console.log(tokyoFormat.format(date));
// 输出:"2025年10月15日 下午9:00 JST"
同一时刻在不同的时区会显示为不同的本地时间。
构建时区选择器
时区选择器需要以用户可以理解的方式呈现数百个选项。通过按区域对时区进行分组,可以使选择更加容易:
const timeZones = Intl.supportedValuesOf("timeZone");
const grouped = timeZones.reduce((groups, tz) => {
const [region] = tz.split("/");
if (!groups[region]) {
groups[region] = [];
}
groups[region].push(tz);
return groups;
}, {});
console.log(Object.keys(grouped));
// 输出: ["Africa", "America", "Antarctica", "Arctic", "Asia",
// "Atlantic", "Australia", "Europe", "Indian", "Pacific", "Etc"]
这种组织方式按大陆对时区进行分组,使用户更容易找到其位置。
您可以通过显示每个时区的当前偏移量进一步改善用户体验:
function getTimeZoneOffset(timeZone) {
const date = new Date();
const formatter = new Intl.DateTimeFormat("en-US", {
timeZone,
timeZoneName: "shortOffset"
});
const parts = formatter.formatToParts(date);
const offsetPart = parts.find(part => part.type === "timeZoneName");
return offsetPart ? offsetPart.value : "";
}
const timeZones = ["America/New_York", "Europe/London", "Asia/Tokyo"];
timeZones.forEach(tz => {
const offset = getTimeZoneOffset(tz);
console.log(`${tz}: ${offset}`);
});
// 输出:
// America/New_York: GMT-4
// Europe/London: GMT+1
// Asia/Tokyo: GMT+9
显示偏移量有助于用户理解时区之间的时间差异。
获取支持的数字系统
数字系统定义了数字的显示方式。虽然大多数应用程序使用标准的阿拉伯数字(0-9),但许多语言有其自己的传统数字系统。
"numberingSystem" 键返回 JavaScript 环境支持的所有数字系统:
const numberingSystems = Intl.supportedValuesOf("numberingSystem");
console.log(numberingSystems.slice(0, 10));
// 输出: ["adlm", "ahom", "arab", "arabext", "armn", "armnlow",
// "bali", "beng", "bhks", "brah"]
常见的数字系统包括:
"latn"表示标准拉丁数字(0-9)"arab"表示阿拉伯-印度数字"thai"表示泰国数字"deva"表示印地语中使用的天城文数字
不同的数字系统以不同的数字形状显示相同的数字:
const number = 12345;
const latinFormat = new Intl.NumberFormat("en-US", {
numberingSystem: "latn"
});
const arabFormat = new Intl.NumberFormat("en-US", {
numberingSystem: "arab"
});
const thaiFormat = new Intl.NumberFormat("en-US", {
numberingSystem: "thai"
});
console.log(latinFormat.format(number));
// 输出: "12,345"
console.log(arabFormat.format(number));
// 输出: "١٢٬٣٤٥"
console.log(thaiFormat.format(number));
// 输出: "๑๒,๓๔๕"
相同的数值以不同的数字形状显示。
获取支持的排序类型
排序类型定义了字符串的排序和比较方式。不同语言对字母顺序有不同的规则。
"collation" 键返回 JavaScript 环境支持的所有排序类型:
const collations = Intl.supportedValuesOf("collation");
console.log(collations.slice(0, 10));
// 输出: ["big5han", "compat", "dict", "direct", "ducet", "emoji",
// "eor", "gb2312", "phonebk", "phonetic"]
常见的排序类型包括:
"standard"表示每种语言的默认排序"phonetic"表示语音排序"pinyin"表示中文拼音排序"emoji"表示表情符号排序
排序会影响字符串数组的排序方式:
const words = ["ä", "z", "a"];
const standardCollator = new Intl.Collator("de-DE", {
collation: "standard"
});
const phoneticCollator = new Intl.Collator("de-DE", {
collation: "phonetic"
});
console.log(words.sort(standardCollator.compare));
// 输出: ["a", "ä", "z"]
console.log(words.sort(phoneticCollator.compare));
// 输出: ["a", "ä", "z"]
不同的排序类型对相同的输入可能会产生不同的排序结果。
获取支持的单位
单位标识符表示测量单位,例如米、加仑或摄氏度。JavaScript 支持许多用于格式化测量值的单位类型。
"unit" 键返回 JavaScript 环境支持的所有单位标识符:
const units = Intl.supportedValuesOf("unit");
console.log(units.slice(0, 10));
// 输出: ["acre", "bit", "byte", "celsius", "centimeter", "day",
// "degree", "fahrenheit", "fluid-ounce", "foot"]
常见的单位包括:
- 长度:
"meter","kilometer","mile","foot" - 重量:
"gram","kilogram","pound","ounce" - 温度:
"celsius","fahrenheit" - 体积:
"liter","gallon" - 数字:
"byte","kilobyte","megabyte"
在格式化测量值时,指定要使用的单位:
const distance = 1000;
const meterFormat = new Intl.NumberFormat("en-US", {
style: "unit",
unit: "meter"
});
const kilometerFormat = new Intl.NumberFormat("en-US", {
style: "unit",
unit: "kilometer"
});
console.log(meterFormat.format(distance));
// 输出: "1,000 m"
console.log(kilometerFormat.format(1));
// 输出: "1 km"
单位决定了数字旁边显示的缩写或符号。
您可以使用格式 "unit1-per-unit2" 组合单位:
const speed = 100;
const speedFormat = new Intl.NumberFormat("en-US", {
style: "unit",
unit: "kilometer-per-hour"
});
console.log(speedFormat.format(speed));
// 输出: "100 km/h"
这会创建复合单位,例如每小时公里数或每加仑英里数。
构建动态用户界面
Intl.supportedValuesOf() 的主要用例是构建能够适应当前 JavaScript 环境的用户界面。与其硬编码选项,不如在运行时查询支持的值。
以下示例创建了一个设置表单,用户可以选择其首选的日历、货币和时区:
function buildSettingsForm() {
const form = document.createElement("form");
// 日历选择器
const calendarSelect = buildSelector(
"calendar",
Intl.supportedValuesOf("calendar")
);
form.appendChild(createFormGroup("日历", calendarSelect));
// 货币选择器
const currencies = ["USD", "EUR", "GBP", "JPY", "CNY"];
const currencySelect = buildSelector("currency", currencies);
form.appendChild(createFormGroup("货币", currencySelect));
// 时区选择器
const timeZones = Intl.supportedValuesOf("timeZone");
const timeZoneSelect = buildSelector("timeZone", timeZones);
form.appendChild(createFormGroup("时区", timeZoneSelect));
return form;
}
function buildSelector(name, values) {
const select = document.createElement("select");
select.name = name;
values.forEach(value => {
const option = document.createElement("option");
option.value = value;
option.textContent = value;
select.appendChild(option);
});
return select;
}
function createFormGroup(label, input) {
const group = document.createElement("div");
const labelElement = document.createElement("label");
labelElement.textContent = label;
group.appendChild(labelElement);
group.appendChild(input);
return group;
}
document.body.appendChild(buildSettingsForm());
这段代码使用仅浏览器支持的值创建了一个完整的设置界面。
使用支持的值进行功能检测
您可以使用 Intl.supportedValuesOf() 检测特定值是否受支持,然后再使用它们。这有助于实现渐进增强和回退策略。
检查特定日历是否受支持:
function isCalendarSupported(calendar) {
const supported = Intl.supportedValuesOf("calendar");
return supported.includes(calendar);
}
if (isCalendarSupported("islamic")) {
console.log("支持伊斯兰日历");
} else {
console.log("不支持伊斯兰日历");
}
此模式适用于任何值类型:
function isValueSupported(type, value) {
try {
const supported = Intl.supportedValuesOf(type);
return supported.includes(value);
} catch (error) {
return false;
}
}
console.log(isValueSupported("currency", "USD"));
// 输出: true
console.log(isValueSupported("timeZone", "America/New_York"));
// 输出: true
try-catch 块处理了 Intl.supportedValuesOf() 不可用的环境。
您可以使用此方法有条件地加载 polyfill:
async function ensureCalendarSupport(calendar) {
if (!isValueSupported("calendar", calendar)) {
console.log(`正在加载 ${calendar} 日历的 polyfill`);
await import("./calendar-polyfill.js");
}
}
await ensureCalendarSupport("persian");
此方法仅在需要时加载额外的代码。