Интерфейсы, ориентированные на международную аудиторию, должны
учитывать не только язык и регион пользователя, но и особенности
восприятия информации людьми с ограниченными возможностями. В экосистеме
JavaScript библиотека Intl API играет важную роль в
создании доступных интерфейсов, поскольку корректное отображение дат,
времени, чисел и текстовых единиц напрямую влияет на работу экранных
дикторов, систем увеличения текста, голосовых помощников и
альтернативных способов ввода.
Неправильно отформатированные данные способны сделать интерфейс практически непригодным для использования:
Intl API предоставляет стандартизированные механизмы
локализации, учитывающие региональные нормы и особенности
доступности.
Часто встречается ручное формирование строк:
const price = 1200;
const result = price + " USD";
Подобный подход имеет ряд проблем:
Для пользователя с нарушением зрения строка:
1200 USD
может быть озвучена хуже, чем локализованный вариант:
1,200 US dollars
Intl.NumberFormat автоматически подбирает формат числа в
зависимости от языка и региона.
const formatter = new Intl.NumberFormat("en-US");
console.log(formatter.format(1234567.89));
Результат:
1,234,567.89
Для немецкой локали:
const formatter = new Intl.NumberFormat("de-DE");
console.log(formatter.format(1234567.89));
Результат:
1.234.567,89
Экранные дикторы интерпретируют такие значения значительно точнее, поскольку формат соответствует ожиданиям пользователя.
Сокращения валют вроде:
1000$
могут озвучиваться неоднозначно.
Корректный вариант:
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
console.log(formatter.format(1000));
Результат:
$1,000.00
Параметр currencyDisplay позволяет управлять способом
отображения валюты.
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
currencyDisplay: "symbol"
}).format(500);
Результат:
$500.00
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
currencyDisplay: "code"
}).format(500);
Результат:
USD 500.00
Наиболее полезно для доступности.
new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
currencyDisplay: "name"
}).format(500);
Результат:
500.00 US dollars
Полное название лучше воспринимается:
Современные интерфейсы часто используют сокращённые формы чисел:
1K
2M
5B
В Intl API это реализуется через
notation.
new Intl.NumberFormat("en-US", {
notation: "compact"
}).format(1200);
Результат:
1.2K
Однако подобный формат может быть неудобен:
Для критически важных интерфейсов рекомендуется обычное форматирование.
Нежелательный вариант:
const result = value + "%";
Корректный способ:
const formatter = new Intl.NumberFormat("ru-RU", {
style: "percent"
});
console.log(formatter.format(0.25));
Результат:
25 %
Intl API автоматически:
Дата — один из самых сложных элементов для интернационализации.
Строка:
01/02/2025
может означать:
const formatter = new Intl.DateTimeFormat("ru-RU");
console.log(formatter.format(new Date()));
Для США:
const formatter = new Intl.DateTimeFormat("en-US");
console.log(formatter.format(new Date()));
Формат автоматически подстраивается под регион.
Для доступности предпочтительны полные текстовые варианты.
const formatter = new Intl.DateTimeFormat("ru-RU", {
dateStyle: "full"
});
console.log(formatter.format(new Date()));
Результат:
понедельник, 10 марта 2025 г.
Такой формат:
const formatter = new Intl.DateTimeFormat("ru-RU", {
timeStyle: "short"
});
console.log(formatter.format(new Date()));
Некоторые пользователи воспринимают только один из вариантов времени.
new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "numeric",
hour12: true
}).format(new Date());
new Intl.DateTimeFormat("de-DE", {
hour: "numeric",
minute: "numeric",
hour12: false
}).format(new Date());
Важно учитывать региональные ожидания пользователей.
Intl.RelativeTimeFormat используется для отображения
относительного времени:
Нежелательный подход:
`${minutes} min ago`
Недостатки:
const formatter = new Intl.RelativeTimeFormat("ru-RU", {
numeric: "auto"
});
console.log(formatter.format(-1, "day"));
Результат:
вчера
Параметр:
numeric: "auto"
позволяет заменять сухие числовые конструкции естественными словами:
вчера
сегодня
завтра
Это особенно полезно:
Intl.ListFormat создаёт корректные списки элементов.
items.join(", ")
Недостатки:
const formatter = new Intl.ListFormat("ru-RU", {
style: "long",
type: "conjunction"
});
console.log(
formatter.format(["HTML", "CSS", "JavaScript"])
);
Результат:
HTML, CSS и JavaScript
Экранные дикторы читают такие конструкции значительно естественнее.
Список с союзом «и».
type: "conjunction"
Список с союзом «или».
type: "disjunction"
Список единиц измерения.
type: "unit"
Intl.DisplayNames преобразует коды в понятные
названия.
Плохо:
USD
RU
fr
Для некоторых пользователей подобные обозначения непонятны.
const formatter = new Intl.DisplayNames(["ru"], {
type: "region"
});
console.log(formatter.of("US"));
Результат:
США
const formatter = new Intl.DisplayNames(["ru"], {
type: "language"
});
console.log(formatter.of("de"));
Результат:
немецкий
Это особенно важно:
Многие языки имеют сложные правила множественного числа.
if (count === 1) {
return "item";
}
Такой код не подходит для большинства языков.
const pluralRules = new Intl.PluralRules("ru-RU");
console.log(pluralRules.select(5));
Результат:
many
В русском языке:
onefewmanyotherconst pluralRules = new Intl.PluralRules("ru-RU");
const forms = {
one: "сообщение",
few: "сообщения",
many: "сообщений",
other: "сообщения"
};
function formatMessages(count) {
const rule = pluralRules.select(count);
return `${count} ${forms[rule]}`;
}
console.log(formatMessages(21));
Результат:
21 сообщение
Корректные склонения улучшают:
Intl.Segmenter предназначен для разбиения текста.
Некоторые языки:
const segmenter = new Intl.Segmenter("ja-JP", {
granularity: "word"
});
const segments = segmenter.segment("こんにちは世界");
for (const item of segments) {
console.log(item.segment);
}
Корректная сегментация помогает:
Intl.NumberFormat поддерживает единицы измерения.
const formatter = new Intl.NumberFormat("ru-RU", {
style: "unit",
unit: "kilometer-per-hour"
});
console.log(formatter.format(80));
Результат:
80 км/ч
unitDisplay: "short"
Результат:
80 км/ч
Наиболее полезно для доступности.
unitDisplay: "long"
Результат:
80 километров в час
Полные названия:
Некоторые методы поддерживают диапазоны.
const formatter = new Intl.DateTimeFormat("ru-RU", {
dateStyle: "medium"
});
console.log(
formatter.formatRange(
new Date("2025-01-01"),
new Date("2025-01-05")
)
);
Результат:
1–5 янв. 2025 г.
Intl API:
Предпочтительно:
currencyDisplay: "name"unitDisplay: "long"dateStyle: "full"Нежелательно:
value + "%"
или
price + " USD"
Полезно:
numeric: "auto"
в Intl.RelativeTimeFormat.
Плохо для доступности:
1K
2M
5B
Разные страны используют:
Большинство возможностей Intl API поддерживаются:
Некоторые современные компоненты (Intl.Segmenter,
formatRange) могут отсутствовать в старых браузерах,
поэтому в крупных проектах рекомендуется проверка поддержки:
if (Intl.Segmenter) {
// поддерживается
}
Для устаревших браузеров используются polyfill-библиотеки:
@formatjs/intl-numberformat@formatjs/intl-datetimeformat@formatjs/intl-relativetimeformatОни обеспечивают одинаковое поведение локализации даже в старых средах выполнения JavaScript.