В современном JavaScript работа с валютами выходит за рамки простого
форматирования чисел. Требуется отображение человекочитаемых
названий валют, адаптированных под локаль пользователя. Для
этой задачи используется Intl.DisplayNames, поддерживающий
тип "currency".
Ключевая особенность:
USD,
EUR, KZT) в локализованные названия;Пример создания экземпляра:
const currencyNames = new Intl.DisplayNames('ru', { type: 'currency' });
console.log(currencyNames.of('USD')); // доллар США
console.log(currencyNames.of('EUR')); // евро
console.log(currencyNames.of('JPY')); // японская иена
Внутри реализована связь с CLDR (Common Locale Data Repository), что обеспечивает единообразие терминологии в разных языках.
Валютные коды в Intl API базируются на стандарте ISO 4217, где каждая валюта представлена трёхбуквенным кодом.
Структура:
Примеры:
| Код | Валюта |
|---|---|
| USD | US Dollar |
| EUR | Euro |
| GBP | British Pound |
| KZT | Kazakhstani Tenge |
| JPY | Japanese Yen |
Intl.DisplayNames работает строго с этими кодами. Любые
отклонения от стандарта приводят к возврату undefined.
Одно и то же значение валюты может иметь разные языковые формы в зависимости от локали.
const ru = new Intl.DisplayNames('ru', { type: 'currency' });
ru.of('USD'); // доллар США
ru.of('EUR'); // евро
const en = new Intl.DisplayNames('en', { type: 'currency' });
en.of('USD'); // US dollar
en.of('EUR'); // euro
const fr = new Intl.DisplayNames('fr', { type: 'currency' });
fr.of('USD'); // dollar des États-Unis
Различия затрагивают:
При передаче некорректного или несуществующего кода поведение строго определено:
const dn = new Intl.DisplayNames('ru', { type: 'currency' });
dn.of('XXX'); // undefined
dn.of('ABC'); // undefined
Особенности:
undefined;Типичная практика — проверка результата:
const name = dn.of(code) ?? 'неизвестная валюта';
Intl.DisplayNames не занимается форматированием чисел.
Его задача — название валюты, а не её отображение в
денежном виде.
const formatter = new Intl.NumberFormat('ru', {
style: 'currency',
currency: 'USD'
});
formatter.format(1000); // 1 000,00 $
const names = new Intl.DisplayNames('ru', { type: 'currency' });
names.of('USD'); // доллар США
Разделение ответственности:
NumberFormat — денежные значения;DisplayNames — текстовые названия сущностей.Частый сценарий — генерация списка валют для выбора:
const currencies = ['USD', 'EUR', 'JPY', 'KZT'];
const dn = new Intl.DisplayNames('ru', { type: 'currency' });
const options = currencies.map(code => ({
code,
name: dn.of(code)
}));
Результат:
[
{ "code": "USD", "name": "доллар США" },
{ "code": "EUR", "name": "евро" },
{ "code": "JPY", "name": "японская иена" },
{ "code": "KZT", "name": "казахстанский тенге" }
]
Если указана локаль, которая не поддерживается, происходит автоматический fallback:
const dn = new Intl.DisplayNames('xx-YY', { type: 'currency' });
dn.of('USD'); // будет использована ближайшая доступная локаль
Алгоритм:
xx);Создание Intl.DisplayNames — относительно дорогая
операция. Поэтому применяется кэширование:
const cache = new Map();
function getCurrencyNames(locale) {
if (!cache.has(locale)) {
cache.set(locale, new Intl.DisplayNames(locale, { type: 'currency' }));
}
return cache.get(locale);
}
Преимущества:
В реальных системах коды валют часто приходят с серверов:
{
"price": 1200,
"currency": "USD"
}
Преобразование:
const dn = new Intl.DisplayNames('ru', { type: 'currency' });
function formatProduct(product) {
return `${product.price} ${dn.of(product.currency)}`;
}
Проверка поддержки:
typeof Intl.DisplayNames === 'function'
Intl.NumberFormatКомбинированное использование:
const number = new Intl.NumberFormat('ru-RU');
const names = new Intl.DisplayNames('ru', { type: 'currency' });
function format(amount, currency) {
return `${number.format(amount)} ${names.of(currency)}`;
}
Intl.LocaleМожно динамически выбирать локаль пользователя:
const locale = navigator.language;
const names = new Intl.DisplayNames(locale, { type: 'currency' });
При обработке массивов транзакций важна оптимизация:
const dn = new Intl.DisplayNames('ru', { type: 'currency' });
function enrichTransactions(transactions) {
return transactions.map(t => ({
...t,
currencyName: dn.of(t.currency)
}));
}
Оптимизационный аспект:
DisplayNames на набор данных;Экземпляр Intl.DisplayNames неизменяем после создания.
Для смены локали требуется новый объект:
let dn = new Intl.DisplayNames('ru', { type: 'currency' });
dn = new Intl.DisplayNames('en', { type: 'currency' });
При проектировании систем часто используется единая модель:
const Currency = {
code: 'USD',
getName(locale) {
return new Intl.DisplayNames(locale, { type: 'currency' }).of(this.code);
}
};
Такой подход: