При разработке международных приложений отображение денежных значений становится одной из ключевых задач локализации. Недостаточно просто вывести числовое значение и символ валюты. Разные страны используют собственные правила:
Библиотека Globalize решает эти задачи через систему CLDR-данных и предоставляет единый API для корректного форматирования валют в различных локалях.
Для форматирования валют требуется:
Globalize;Пример базовой настройки:
const Globalize = require("globalize");
Globalize.load(
require("cldr-data/supplemental/likelySubtags.json"),
require("cldr-data/main/en/numbers.json"),
require("cldr-data/main/en/currencies.json")
);
Globalize.locale("en");
После загрузки можно создавать форматтер валют.
Базовый пример:
const formatter = Globalize.currencyFormatter("USD");
console.log(formatter(1500));
// $1,500.00
Метод currencyFormatter() возвращает функцию
форматирования, которая автоматически применяет правила текущей
локали.
Одинаковая валюта может отображаться по-разному в зависимости от языка и региона.
Пример:
const amount = 1500;
Globalize.locale("en-US");
const formatter = Globalize.currencyFormatter("USD");
console.log(formatter(amount));
Результат:
$1,500.00
Символ валюты расположен перед числом без пробела.
Globalize.locale("fr");
const formatter = Globalize.currencyFormatter("USD");
console.log(formatter(amount));
Результат:
1 500,00 $US
Особенности:
$US.Globalize.locale("ru");
const formatter = Globalize.currencyFormatter("RUB");
console.log(formatter(amount));
Результат:
1 500,00 ₽
Символ рубля располагается после числа.
Globalize не требует ручной настройки позиции валюты. Библиотека использует данные Unicode CLDR и автоматически определяет:
Это особенно важно для многоязычных интерфейсов.
Globalize.locale("de");
const formatter = Globalize.currencyFormatter("EUR");
console.log(formatter(2999.95));
Результат:
2.999,95 €
В немецкой локали:
Globalize.locale("ja");
const formatter = Globalize.currencyFormatter("JPY");
console.log(formatter(5000));
Результат:
¥5,000
Для иены дробная часть отсутствует.
Globalize.locale("en-GB");
const formatter = Globalize.currencyFormatter("GBP");
console.log(formatter(120));
Результат:
£120.00
В некоторых случаях символ валюты может быть неоднозначным.
Например:
$ используется для USD, CAD, AUD;kr используется в нескольких странах;£ может обозначать разные валюты.Globalize позволяет выводить код валюты.
const formatter = Globalize.currencyFormatter("USD", {
style: "code"
});
console.log(formatter(100));
Результат:
USD 100.00
const formatter = Globalize.currencyFormatter("USD", {
style: "name"
});
console.log(formatter(100));
Результат:
100.00 US dollars
Globalize.currencyFormatter("EUR")(100);
€100.00
Globalize.currencyFormatter("EUR", {
style: "code"
})(100);
EUR 100.00
Globalize.currencyFormatter("EUR", {
style: "name"
})(100);
100.00 euros
Многие локали используют не обычный пробел, а специальный неразрывный символ.
Пример французской локали:
1 500,00 €
Используются:
Это предотвращает перенос символа валюты на новую строку.
Ошибка:
price + " $"
Проблемы такого подхода:
Globalize.locale("en");
const formatter = Globalize.currencyFormatter("USD");
console.log(formatter(-100));
Результат:
-$100.00
В некоторых странах отрицательные суммы оформляются иначе:
Globalize автоматически применяет нужные правила CLDR.
RTL-языки требуют особого подхода.
Пример арабской локали:
Globalize.locale("ar");
const formatter = Globalize.currencyFormatter("USD");
console.log(formatter(100));
Результат может выглядеть так:
100.00 US$
Библиотека корректно обрабатывает:
const formatter = Globalize.numberFormatter({
style: "currency",
currency: "USD",
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
console.log(formatter(25));
Результат:
$25.00
const formatter = Globalize.numberFormatter({
style: "currency",
currency: "USD",
maximumFractionDigits: 0
});
console.log(formatter(25.75));
Результат:
$26
currencyFormatter и numberFormatterСпециализированный метод для валют:
Globalize.currencyFormatter("USD");
Подходит для большинства задач.
Более гибкий вариант:
Globalize.numberFormatter({
style: "currency",
currency: "USD"
});
Позволяет дополнительно управлять:
CLDR не всегда содержит данные о криптовалютах. В таких случаях можно использовать код валюты.
const formatter = Globalize.numberFormatter({
minimumFractionDigits: 8,
maximumFractionDigits: 8
});
console.log(formatter(0.12345678) + " BTC");
Результат:
0.12345678 BTC
Создание форматтера — относительно дорогая операция.
Неправильно:
function format(price) {
return Globalize.currencyFormatter("USD")(price);
}
Каждый вызов создаёт новый форматтер.
const usdFormatter =
Globalize.currencyFormatter("USD");
function format(price) {
return usdFormatter(price);
}
const prices = [
{ value: 10, currency: "USD" },
{ value: 20, currency: "EUR" },
{ value: 3000, currency: "JPY" }
];
const formatters = {
USD: Globalize.currencyFormatter("USD"),
EUR: Globalize.currencyFormatter("EUR"),
JPY: Globalize.currencyFormatter("JPY")
};
prices.forEach(item => {
console.log(
formatters[item.currency](item.value)
);
});
Плохо:
"$" + amount
Плохо:
amount.toFixed(2)
Такой код не учитывает:
Плохо:
const price = "$100.00";
Лучше хранить:
{
value: 100,
currency: "USD"
}
Форматирование должно происходить только на этапе отображения.
const usdFormatter =
Globalize.currencyFormatter("USD");
function Price({ value }) {
return (
<span>{usdFormatter(value)}</span>
);
}
methods: {
formatPrice(value) {
return this.formatter(value);
}
}
formatPrice(value: number) {
return this.usdFormatter(value);
}
При отображении тысяч цен:
class CurrencyService {
constructor(locale) {
Globalize.locale(locale);
this.formatters = {};
}
format(value, currency) {
if (!this.formatters[currency]) {
this.formatters[currency] =
Globalize.currencyFormatter(currency);
}
return this.formatters[currency](value);
}
}
$1,999.99
1.999,99 €
1 999,99 ₽
¥1,999
1 999,99 €
const en = new Globalize("en");
const fr = new Globalize("fr");
const ru = new Globalize("ru");
const usd = en.currencyFormatter("USD");
const eur = fr.currencyFormatter("EUR");
const rub = ru.currencyFormatter("RUB");
console.log(usd(100));
console.log(eur(100));
console.log(rub(100));
При тестировании валют необходимо проверять:
Globalize использует данные CLDR:
numbers.jsoncurrencies.jsonНа основе этих файлов библиотека определяет:
Благодаря этому форматирование остаётся одинаково корректным для десятков языков и регионов.