Как проверить, какую локаль и параметры фактически использует форматтер?

Используйте метод 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);
// Вероятно, вывод: 'de-AT' или 'de'

console.log(options.calendar);
// Вероятно, вывод: 'gregory' (если буддийский календарь не поддерживается)

Во-вторых, браузер заполняет значения по умолчанию для любых параметров, которые вы не указываете. Эти значения по умолчанию зависят от локали.

const formatter = new Intl.NumberFormat('en-US');
const options = formatter.resolvedOptions();

console.log(options.style);
// Вывод: 'decimal'

console.log(options.minimumFractionDigits);
// Вывод: 0

console.log(options.maximumFractionDigits);
// Вывод: 3

В-третьих, браузер нормализует определённые параметры в их каноническую форму. Если вы используете dateStyle или timeStyle, браузер не включает их в разрешённые параметры. Вместо этого он включает отдельные параметры компонентов, на которые они разворачиваются.

Проверка фактически используемой локали

locale в свойствах resolved options точно указывает, какую локаль использует форматтер. Это результат согласования локалей.

const formatter = new Intl.DateTimeFormat(['zh-TW', 'zh-CN', 'en-US']);
const options = formatter.resolvedOptions();

console.log(options.locale);
// Выводит первую поддерживаемую локаль из списка

Если вы запрашиваете локаль с ключевыми словами расширения Unicode, результирующая локаль может не включать эти ключевые слова, если они не поддерживаются или были применены как отдельные параметры.

const formatter = new Intl.NumberFormat('en-US-u-nu-arab');
const options = formatter.resolvedOptions();

console.log(options.locale);
// Может вывести: 'en-US'

console.log(options.numberingSystem);
// Может вывести: 'arab' или 'latn' в зависимости от поддержки

Изучение параметров форматирования даты и времени

Для Intl.DateTimeFormat resolved options включают детали о том, какие компоненты даты и времени будут отображаться и как.

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);
// Выводит: 'numeric'

console.log(options.month);
// Выводит: 'long'

console.log(options.day);
// Выводит: 'numeric'

console.log(options.timeZone);
// Выводит: 'America/New_York'

console.log(options.calendar);
// Выводит: 'gregory'

Когда вы используете dateStyle или timeStyle, эти сокращения не включаются в resolved options. Браузер разворачивает их в отдельные параметры компонентов на основе локали.

const formatter = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'full'
});

const options = formatter.resolvedOptions();

console.log(options.dateStyle);
// Выводит: undefined

console.log(options.weekday);
// Выводит: 'long'

console.log(options.year);
// Выводит: 'numeric'

console.log(options.month);
// Выводит: 'long'

console.log(options.day);
// Выводит: 'numeric'

Если вы создаете форматтер даты без каких-либо параметров, resolved options покажут, какие параметры по умолчанию выбрал браузер для этой локали.

const formatter = new Intl.DateTimeFormat('ja-JP');
const options = formatter.resolvedOptions();

console.log(options);
// Показывает параметры компонентов даты по умолчанию для японской локали

Изучение параметров форматирования чисел

Для Intl.NumberFormat метод resolvedOptions предоставляет информацию о стиле, точности, группировке и других деталях форматирования.

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

const options = formatter.resolvedOptions();

console.log(options.style);
// Вывод: 'currency'

console.log(options.currency);
// Вывод: 'USD'

console.log(options.currencyDisplay);
// Вывод: 'symbol'

console.log(options.minimumFractionDigits);
// Вывод: 2

console.log(options.maximumFractionDigits);
// Вывод: 2

Вы можете заметить, что, даже указав только валюту, браузер заполнил значения по умолчанию для currencyDisplay и дробных разрядов.

Когда вы используете параметры округления, метод resolvedOptions показывает, как именно будут округляться числа.

const formatter = new Intl.NumberFormat('en-US', {
  minimumSignificantDigits: 3,
  maximumSignificantDigits: 5
});

const options = formatter.resolvedOptions();

console.log(options.minimumSignificantDigits);
// Вывод: 3

console.log(options.maximumSignificantDigits);
// Вывод: 5

Изучение других типов форматировщиков

Метод resolvedOptions() работает одинаково для всех форматировщиков Intl.

Для Intl.ListFormat он показывает тип и стиль.

const formatter = new Intl.ListFormat('en-US', {
  style: 'long',
  type: 'conjunction'
});

const options = formatter.resolvedOptions();

console.log(options.locale);
// Вывод: 'en-US'

console.log(options.style);
// Вывод: 'long'

console.log(options.type);
// Вывод: 'conjunction'

Для Intl.PluralRules он показывает тип и минимальное/максимальное количество разрядов.

const formatter = new Intl.PluralRules('en-US', {
  type: 'ordinal'
});

const options = formatter.resolvedOptions();

console.log(options.locale);
// Вывод: 'en-US'

console.log(options.type);
// Вывод: 'ordinal'

console.log(options.minimumIntegerDigits);
// Вывод: 1

Общие случаи использования resolvedOptions()

Наиболее распространенный случай использования — отладка. Когда отформатированный вывод не соответствует вашим ожиданиям, resolvedOptions() помогает понять, что именно делает форматировщик.

const formatter = new Intl.DateTimeFormat('en-US', {
  dateStyle: 'medium'
});

console.log(formatter.format(new Date()));
// Проверьте вывод

console.log(formatter.resolvedOptions());
// Узнайте, какие параметры привели к этому выводу

Другой случай использования — обнаружение возможностей. Вы можете проверить, поддерживается ли определенный календарь, система нумерации или другая функция, запросив её и посмотрев, что было фактически разрешено.

const formatter = new Intl.DateTimeFormat('en-US', {
  calendar: 'islamic'
});

const options = formatter.resolvedOptions();

if (options.calendar === 'islamic') {
  console.log('Исламский календарь поддерживается');
} else {
  console.log('Исламский календарь не поддерживается, используется ' + options.calendar);
}

Вы также можете использовать resolvedOptions() для получения предпочтений локали пользователя. Когда вы создаете форматировщик без аргумента локали, браузер использует предпочтения пользователя.

const formatter = new Intl.DateTimeFormat();
const options = formatter.resolvedOptions();

console.log(options.locale);
// Вывод: предпочтительная локаль пользователя

console.log(options.timeZone);
// Вывод: часовой пояс пользователя

console.log(options.hourCycle);
// Вывод: предпочтение пользователя по формату времени (12 или 24 часа)

Наконец, вы можете использовать разрешенные параметры для создания идентичного форматировщика. Возвращенный объект можно передать обратно в конструктор.

const formatter1 = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

const options = formatter1.resolvedOptions();

const formatter2 = new Intl.NumberFormat(options.locale, options);

// formatter2 будет форматировать числа так же, как formatter1

Основные выводы

Метод resolvedOptions() возвращает объект, содержащий фактическую конфигурацию, которую использует форматтер. Эта конфигурация может отличаться от запрошенной вами из-за согласования локали, значений по умолчанию и нормализации.

Каждый форматтер Intl имеет этот метод. Вы вызываете его без параметров и получаете объект со свойствами, такими как locale, calendar, numberingSystem и специфические для форматтера опции.

Используйте resolvedOptions() в основном для отладки поведения форматтера, обнаружения доступных функций и понимания того, как браузер интерпретировал ваши параметры. Возвращаемый объект также можно использовать для создания идентичного форматтера или анализа предпочтений пользователя.