Как узнать, какой язык и параметры реально использует форматтер?
Используйте метод resolvedOptions(), чтобы посмотреть фактическую конфигурацию любого Intl форматтера
Введение
Когда вы создаёте форматтер Intl в JavaScript, запрошенные вами параметры не всегда совпадают с теми, что реально используются. Браузер проводит согласование локали, подставляет значения по умолчанию и нормализует ваши настройки, чтобы получить итоговую конфигурацию. Метод resolvedOptions() позволяет узнать, какие именно параметры применяются в итоге.
У каждого форматтера в API Intl есть метод 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 для форматтеров чисел. Дополнительные свойства зависят от указанных вами опций и типа форматтера.
Почему запрошенные параметры отличаются от итоговых
Есть три основные причины, почему параметры, которые вы запрашиваете, могут отличаться от тех, что реально используются.
Во-первых, при согласовании локали выбирается наиболее подходящая локаль, если ваша точная локаль не поддерживается. Например, если вы запрашиваете de-AT, а в браузере есть только de, итоговой локалью будет 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)
Во-вторых, браузер подставляет значения по умолчанию для любых опций, которые вы не указали. Эти значения зависят от локали.
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 в итоговых опциях показывает, какую именно локаль использует форматтер. Это результат согласования локалей.
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
Если вы запрашиваете локаль с ключевыми словами расширения Unicode, итоговая локаль может не содержать эти ключевые слова, если они не поддерживаются или были применены как отдельные опции.
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, эти сокращения не включаются в итоговые опции. Браузер разворачивает их в отдельные компонентные опции в зависимости от локали.
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'
Если вы создаёте форматтер даты без каких-либо опций, итоговые опции покажут, что браузер выбрал по умолчанию для этой локали.
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 и количества знаков после запятой.
Когда вы используете параметры округления, в результатах отображается, как именно будут округляться числа.
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(), чтобы получить предпочтения пользователя по локали. Если вы создаёте форматтер без указания локали, браузер использует настройки пользователя.
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)
Наконец, вы можете использовать полученные параметры, чтобы создать идентичный форматтер. Возвращаемый объект можно передать обратно в конструктор.
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() в основном для отладки поведения форматтера, определения доступных функций и понимания того, как браузер интерпретировал ваши параметры. Возвращаемый объект также можно использовать для воссоздания идентичного форматтера или для просмотра пользовательских настроек.