JavaScript Internationalization API (сокращенно Intl) предоставляет мощные инструменты для форматирования чисел, дат, времени и сравнения строк с учетом языковых и региональных особенностей. Этот API состоит из трех основных классов: Intl.NumberFormat, Intl.DateTimeFormat и Intl.Collator.
Важно понимать, что эти классы не являются частью стандарта ECMAScript, а определены в стандарте ECMA402. Они хорошо поддерживаются современными браузерами, но в Node.js могут потребовать дополнительной настройки для работы с локалями, отличными от американского английского.
Разные регионы мира используют различные форматы для отображения чисел. Различаются десятичные разделители (точки или запятые), разделители тысяч, форматы отображения валют и даже сами цифры могут отличаться в некоторых языках.
Конструктор Intl.NumberFormat принимает два аргумента:
- Локаль (строка или массив строк)
- Объект с настройками форматирования
// Простой пример
const formatter = new Intl.NumberFormat('ru-RU');
console.log(formatter.format(1234567.89)); // "1 234 567,89"
// Форматирование валют
const euroFormatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
});
console.log(euroFormatter.format(1000)); // "1.000,00 €"- style: тип форматирования ("decimal", "percent", "currency")
- currency: трехбуквенный код валюты (требуется при style: "currency")
- currencyDisplay: как отображать валюту ("symbol", "code", "name")
- useGrouping: использовать ли разделители тысяч
- minimumIntegerDigits: минимальное количество цифр в целой части
- minimumFractionDigits/maximumFractionDigits: ограничения для дробной части
- minimumSignificantDigits/maximumSignificantDigits: ограничения для значащих цифр
// Проценты
const percentFormatter = new Intl.NumberFormat('ru-RU', {
style: 'percent',
minimumFractionDigits: 1,
maximumFractionDigits: 1
});
console.log(percentFormatter.format(0.123)); // "12,3%"
// Использование связанного метода format
const data = [0.05, 0.75, 1];
const formatPercent = new Intl.NumberFormat('ru-RU', {
style: 'percent',
minimumFractionDigits: 1,
maximumFractionDigits: 1
}).format;
console.log(data.map(formatPercent)); // ["5,0%", "75,0%", "100,0%"]Некоторые языки используют собственные системы числения:
// Арабские цифры
const arabicFormatter = new Intl.NumberFormat('ar', {
useGrouping: false
}).format;
console.log(arabicFormatter(1234567890)); // "١٢٣٤٥٦٧٨٩٠"
// Индийские цифры (деванагари)
const hindiFormatter = new Intl.NumberFormat('hi-IN-u-nu-deva').format;
console.log(hindiFormatter(1234567890)); // "१,२३,४५,६७,८९०"Примечание: суффикс -u-nu-deva в локали указывает на использование системы числения деванагари.
Класс Intl.DateTimeFormat предоставляет гибкие возможности для форматирования дат и времени с учетом региональных особенностей.
const date = new Date('2020-01-02T13:14:15Z');
// Базовое форматирование
const usFormatter = new Intl.DateTimeFormat('en-US');
console.log(usFormatter.format(date)); // "1/2/2020"
const frFormatter = new Intl.DateTimeFormat('fr-FR');
console.log(frFormatter.format(date)); // "02/01/2020"- year: "numeric" или "2-digit"
- month: "numeric", "2-digit", "long", "short", "narrow"
- day: "numeric" или "2-digit"
- weekday: "long", "short", "narrow"
- era: "long", "short", "narrow" (для отображения эр, например, "н.э.")
- hour, minute, second: "numeric" или "2-digit"
- timeZone: указание часового пояса
- timeZoneName: "long" или "short" для отображения названия пояса
- hour12: true/false для 12-часового формата
- hourCycle: "h11", "h12", "h23", "h24"
const date = new Date('2020-01-02T13:14:15Z');
// Полное форматирование с указанием дня недели и месяца
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
};
const usFullFormatter = new Intl.DateTimeFormat('en-US', options);
console.log(usFullFormatter.format(date)); // "Thursday, January 2, 2020"
const esFullFormatter = new Intl.DateTimeFormat('es-ES', options);
console.log(esFullFormatter.format(date)); // "jueves, 2 de enero de 2020"
// Форматирование времени с указанием часового пояса
const timeOptions = {
hour: 'numeric',
minute: '2-digit',
timeZone: 'America/New_York'
};
const frTimeFormatter = new Intl.DateTimeFormat('fr-CA', timeOptions);
console.log(frTimeFormatter.format(date)); // "8 h 14"Intl.DateTimeFormat поддерживает различные календарные системы:
const date = new Date('2020-01-02T13:14:15Z');
const options = { year: 'numeric', era: 'short' };
// Разные календарные системы
console.log(new Intl.DateTimeFormat('en', options).format(date)); // "2020 AD"
console.log(new Intl.DateTimeFormat('en-u-ca-hebrew', options).format(date)); // "5780 AM"
console.log(new Intl.DateTimeFormat('en-u-ca-islamic', options).format(date)); // "1441 AH"
console.log(new Intl.DateTimeFormat('en-u-ca-japanese', options).format(date)); // "2 Reiwa"Примечание: суффикс -u-ca- в локали указывает на использование alternative календарной системы.
Сортировка строк - более сложная задача, чем может показаться. Разные языки имеют различные правила алфавитной сортировки, учитывающие специфические символы и диграфы.
// Базовый компаратор для локали пользователя
const collator = new Intl.Collator().compare;
const words = ['a', 'z', 'A', 'Z'];
console.log(words.sort(collator)); // ["a", "A", "z", "Z"]- usage: "sort" (по умолчанию) или "search"
- sensitivity: "base", "accent", "case" или "variant"
- ignorePunctuation: игнорировать ли пунктуацию
- numeric: числовое сравнение вместо строкового
- caseFirst: какой регистр должен идти первым ("upper" или "lower")
// Числовая сортировка (полезно для имен файлов)
const numericCollator = new Intl.Collator(undefined, { numeric: true }).compare;
const filenames = ['page10', 'page9'];
console.log(filenames.sort(numericCollator)); // ["page9", "page10"]
// Нечеткое сравнение для поиска
const fuzzyCollator = new Intl.Collator(undefined, {
sensitivity: 'base',
ignorePunctuation: true
}).compare;
const strings = ['food', 'fool', 'Føø Bar'];
const target = 'foobar';
const result = strings.findIndex(s => fuzzyCollator(s, target) === 0);
console.log(result); // 2 (соответствует "Føø Bar")Некоторые локали имеют несколько вариантов сортировки:
// Современная и традиционная испанская сортировка
const modernSpanish = new Intl.Collator('es-ES').compare;
const traditionalSpanish = new Intl.Collator('es-ES-u-co-trad').compare;
const words = ['luz', 'llama', 'como', 'chico'];
console.log(words.sort(modernSpanish)); // ["chico", "como", "llama", "luz"]
console.log(words.sort(traditionalSpanish)); // ["como", "chico", "luz", "llama"]Примечание: суффикс -u-co- в локали указывает на использование alternative варианта сортировки.
Internationalization API предоставляет мощные инструменты для создания интернационализированных приложений на JavaScript. Основные преимущества:
- Локаль-зависимое форматирование чисел, дат и валют
- Гибкие настройки для точного контроля над отображением
- Корректное сравнение строк с учетом языковых особенностей
- Широкая поддержка в современных браузерах
Использование этих API не только улучшает пользовательский опыт, но и показывает уважение к культурным особенностям пользователей из разных регионов мира.
Для дальнейшего изучения рекомендуется экспериментировать с различными локалями и настройками, чтобы понять все возможности Internationalization API.