JavaScript Intl (Internationalization) API
Изучите встроенный JavaScript Intl API для форматирования чисел, валют, дат, относительного времени и списков для любой локали, а также корректной сортировки строк.
Intl — это встроенное пространство имён JavaScript для форматирования и сравнения с учётом локали. Не нужно ничего устанавливать и ничего импортировать — он поставляется с каждым современным браузером и Node.js. С его помощью можно форматировать числа, валюты, даты, относительное время и списки именно так, как того ожидают пользователи в конкретном регионе, а также правильно сортировать текст для языков, где сортировка только по английским правилам даёт неверный результат.
Почти каждый конструктор Intl имеет одинаковую структуру: вы передаёте локаль (или массив резервных локалей) и объект options. Локаль — это языковой тег BCP 47, например 'en-US', 'de-DE', 'fr-FR' или 'ja-JP'. Если локаль не указана, Intl использует локаль среды выполнения по умолчанию (настройки языка браузера или системную локаль в Node).
// locale + options
new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' });
// no locale → uses the runtime default
new Intl.NumberFormat();
// an array provides fallbacks: try Welsh, then fall back to English
new Intl.NumberFormat(['cy', 'en']);Intl.NumberFormat
Intl.NumberFormat форматирует числа в соответствии с соглашениями локали. Это важно, потому что разделители групп и дробей различаются в зависимости от места: число 1234.56 записывается как 1,234.56 в Соединённых Штатах, но 1.234,56 в Германии.
const n = 1234.56;
console.log(new Intl.NumberFormat('en-US').format(n)); // "1,234.56"
console.log(new Intl.NumberFormat('de-DE').format(n)); // "1.234,56"
console.log(new Intl.NumberFormat('fr-FR').format(n)); // "1 234,56"Опция style определяет тип форматируемого значения: 'decimal' (по умолчанию), 'currency', 'percent' или 'unit'.
Валюта
Для денежных значений установите style: 'currency' и укажите валюту с помощью опции currency (код ISO 4217, например 'USD' или 'EUR'). Локаль определяет положение символа и разделители.
const price = 1499.9;
console.log(
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(price)
); // "$1,499.90"
console.log(
new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(price)
); // "1.499,90 €"
console.log(
new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(price)
); // "¥1,500" (yen has no minor unit, so it is rounded)Проценты, количество знаков после запятой и компактная нотация
Используйте style: 'percent' для форматирования дроби в виде процентов — значение умножается на 100. Управляйте количеством отображаемых знаков после запятой с помощью minimumFractionDigits и maximumFractionDigits. Установите notation: 'compact', чтобы получить краткие формы, такие как 1.2K и 3.4M.
console.log(
new Intl.NumberFormat('en-US', { style: 'percent' }).format(0.1875)
); // "19%"
console.log(
new Intl.NumberFormat('en-US', {
style: 'percent',
minimumFractionDigits: 2,
}).format(0.1875)
); // "18.75%"
console.log(
new Intl.NumberFormat('en-US', { notation: 'compact' }).format(1200000)
); // "1.2M"Единицы измерения
С помощью style: 'unit' можно форматировать величины. Укажите единицу с помощью опции unit (например, 'kilometer-per-hour' или 'megabyte') и выберите unitDisplay: 'short', 'long' или 'narrow'.
console.log(
new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer-per-hour',
}).format(90)
); // "90 km/h"
console.log(
new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'megabyte',
unitDisplay: 'long',
}).format(16)
); // "16 megabytes"Для более сложной работы с числами — округление, точность и арифметика — см. Numbers и JavaScript Math.
Intl.DateTimeFormat
Intl.DateTimeFormat форматирует объекты Date (и временны́е метки) для заданной локали. Самый быстрый подход — опции dateStyle и timeStyle, каждая из которых принимает значения 'full', 'long', 'medium' или 'short'.
Для более тонкого управления задайте отдельные компоненты, такие как year, month, day, hour, minute и second, и привяжите вывод к нужному часовому поясу с помощью timeZone.
const date = new Date('2026-06-19T14:30:00Z');
const fmt = new Intl.DateTimeFormat('en-GB', {
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
timeZone: 'Europe/Berlin',
});
console.log(fmt.format(date)); // "19 Jun 2026, 16:30"Стоит знать два дополнительных метода. .formatToParts() возвращает результат, разбитый на именованные части ({ type: 'month', value: 'Jun' } и т. д.), что позволяет стилизовать каждую часть отдельно. .formatRange(start, end) компактно форматирует диапазон дат, сворачивая общие части.
const fmt = new Intl.DateTimeFormat('en-US', { month: 'long', day: 'numeric' });
console.log(fmt.formatRange(new Date(2026, 5, 1), new Date(2026, 5, 5)));
// "June 1 – 5"Всё о создании дат и работе с ними см. в разделе JavaScript Date.
Intl.RelativeTimeFormat
Intl.RelativeTimeFormat формирует понятные фразы вроде «2 дня назад» или «через 3 часа». Вы вызываете .format(value, unit), где отрицательное value означает прошлое, а положительное — будущее. Опция numeric: 'auto' позволяет форматтеру использовать слова вроде «вчера» и «завтра» вместо «1 день назад».
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtf.format(-1, 'day')); // "yesterday"
console.log(rtf.format(3, 'hour')); // "in 3 hours"
console.log(rtf.format(-2, 'day')); // "2 days ago"
console.log(rtf.format(1, 'week')); // "next week"Тот же вызов в другой локали даёт нативную формулировку — new Intl.RelativeTimeFormat('fr').format(-1, 'day') возвращает "il y a 1 jour".
Intl.Collator
Сортировка текста — это место, где наивный код чаще всего даёт неверный результат. Стандартный Array.prototype.sort() в JavaScript сравнивает строки по их кодовым единицам UTF-16, а не по алфавитным правилам. Это означает, что заглавные буквы сортируются перед строчными, а буквы с диакритическими знаками или не латинские символы оказываются на неожиданных позициях.
const words = ['Zürich', 'apple', 'Banana', 'Älpler'];
console.log([...words].sort());
// ["Banana", "Zürich", "Älpler", "apple"] ← not what a reader expectsIntl.Collator исправляет это, сравнивая строки так, как это принято в конкретном языке. Его метод .compare имеет именно ту сигнатуру, которую ожидает sort(), поэтому его можно передать напрямую.
Для разового сравнения двух строк можно также использовать String.prototype.localeCompare, который принимает те же аргументы локали и опций: 'ä'.localeCompare('z', 'de'). При сортировке целого array предпочтительнее использовать переиспользуемый Intl.Collator — это быстрее, чем вызывать localeCompare для каждой пары. Подробнее о работе с текстом см. в разделе Strings.
Intl.PluralRules
В разных языках разные категории множественного числа. В английском их всего две ('one' и 'other'), но во многих языках их больше. Intl.PluralRules сообщает, к какой категории относится число, чтобы вы могли выбрать правильную формулировку в переведённом сообщении.
const pr = new Intl.PluralRules('en-US');
console.log(pr.select(0)); // "other"
console.log(pr.select(1)); // "one"
console.log(pr.select(5)); // "other"
function items(count) {
const word = pr.select(count) === 'one' ? 'item' : 'items';
return `${count} ${word}`;
}
console.log(items(1)); // "1 item"
console.log(items(3)); // "3 items"Intl.ListFormat
Intl.ListFormat объединяет array строк в естественно звучащий список, вставляя правильные разделители и союзы для данной локали — включая Оксфордскую запятую там, где её использует язык.
const items = ['apples', 'bananas', 'oranges'];
const en = new Intl.ListFormat('en-US', { style: 'long', type: 'conjunction' });
console.log(en.format(items)); // "apples, bananas, and oranges"
const enOr = new Intl.ListFormat('en-US', { type: 'disjunction' });
console.log(enOr.format(items)); // "apples, bananas, or oranges"
const de = new Intl.ListFormat('de-DE', { type: 'conjunction' });
console.log(de.format(items)); // "apples, bananas und oranges"Повторное использование форматтеров для производительности
Создание форматтера Intl сравнительно затратно — оно загружает и разрешает данные локали. Создавайте каждый форматтер один раз и переиспользуйте его, особенно внутри циклов или при отрисовке списков. Создание нового new Intl.NumberFormat(...) для каждой строки может быть значительно медленнее, чем само форматирование.
// Slow: a new formatter is built on every iteration
prices.forEach((p) =>
console.log(new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(p))
);
// Fast: build it once, reuse it
const money = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' });
prices.forEach((p) => console.log(money.format(p)));Каждый форматтер также предоставляет метод .resolvedOptions(), который сообщает о локали и опциях, фактически выбранных после согласования. Это удобно для отладки случаев, когда среда выполнения переключается на локаль, отличную от запрошенной.
Итоги
API Intl охватывает задачи форматирования и сравнения, которые раньше требовали громоздких сторонних библиотек: числа, валюты, даты, относительное время, множественные числа и списки с учётом локали, а также корректную сортировку текста через Intl.Collator. Поскольку он встроен в каждый современный браузер и в Node.js, его использование в первую очередь сохраняет ваш бандл небольшим, а вывод — корректным для пользователей по всему миру. Запомните одно правило, которое приносит наибольшую пользу: создавайте каждый форматтер один раз и переиспользуйте его.