Как форматировать валюту с учетом локальных символов
Отображайте цены с правильным символом валюты, расположением и форматом для любой локали
Введение
Символы валюты указывают, к какой валюте относится цена. Знак доллара обозначает доллары США, символ евро обозначает евро, а знак фунта обозначает британские фунты. Эти символы важны для международных приложений, так как пользователи должны знать, в какой валюте они просматривают или тратят деньги.
Разные страны по-разному форматируют суммы в валюте. Американцы пишут $1,234.56 с символом перед суммой. Немцы пишут 1.234,56 € с символом после суммы и другими разделителями. Французский формат использует 1 234,56 € с пробелами между группами цифр. Когда вы жестко задаете форматирование валюты, например, "$" + amount, вы предполагаете, что все пользователи следуют одним и тем же правилам.
JavaScript предоставляет API Intl.NumberFormat для форматирования сумм в валюте с учетом символов и правил, соответствующих локали. Этот урок объясняет, как форматирование валюты различается в зависимости от локали и как правильно форматировать цены для любого языка или региона.
Символы валюты различаются в зависимости от локали
Разные валюты используют разные символы. Доллар США обозначается $, евро — €, британский фунт — £, японская иена — ¥, а швейцарский франк — Fr. или CHF в зависимости от контекста. Каждый символ помогает пользователям быстро определить, какую валюту они видят.
Некоторые символы представляют несколько валют. Знак доллара $ используется для долларов США, канадских долларов, австралийских долларов, мексиканских песо и нескольких других валют. Без дополнительного контекста пользователи не могут определить, к какой именно валюте относится цена.
Позиция символа валюты варьируется в зависимости от локали. В англоязычных странах символ обычно размещается перед суммой, например, $100. Во многих европейских странах символ размещается после суммы, например, 100 €. В некоторых странах между суммой и символом ставится пробел, в других — нет.
Эти различия означают, что вы не можете просто объединить символ и число. Вам нужна логика форматирования, которая учитывает как отображаемую валюту, так и локаль пользователя, который ее просматривает.
Форматирование валюты с помощью Intl.NumberFormat
Intl.NumberFormat создаёт форматировщик валюты, если в параметрах передать style: 'currency'. Также необходимо указать, какую валюту форматировать, используя параметр currency с кодом валюты по стандарту ISO 4217.
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
console.log(formatter.format(1234.56));
// Вывод: "$1,234.56"
Этот код создаёт форматировщик для американского английского, который отображает суммы в долларах США. Метод format() преобразует число в строку с символом доллара, разделителями тысяч и двумя десятичными знаками.
Параметр currency требует трёхбуквенный код валюты по стандарту ISO 4217. Примеры популярных кодов: USD для долларов США, EUR для евро, GBP для фунтов стерлингов, JPY для японских йен и CAD для канадских долларов.
const usdFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
const eurFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'EUR'
});
const gbpFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'GBP'
});
console.log(usdFormatter.format(100));
// Вывод: "$100.00"
console.log(eurFormatter.format(100));
// Вывод: "€100.00"
console.log(gbpFormatter.format(100));
// Вывод: "£100.00"
Каждый форматировщик автоматически добавляет соответствующий символ валюты. Вам не нужно знать, какой символ соответствует каждому коду валюты.
Локаль определяет позицию символа и форматирование
Параметр локали управляет тем, как форматируются суммы валюты, включая позицию символа, разделение разрядов и десятичные разделители. Один и тот же код валюты может давать разный результат в зависимости от локали.
const usFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'EUR'
});
const deFormatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
});
const frFormatter = new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR'
});
console.log(usFormatter.format(1234.56));
// Вывод: "€1,234.56"
console.log(deFormatter.format(1234.56));
// Вывод: "1.234,56 €"
console.log(frFormatter.format(1234.56));
// Вывод: "1 234,56 €"
Все три форматировщика отображают евро, но используют разные соглашения. Форматировщик для американского английского размещает символ перед суммой и использует точку в качестве десятичного разделителя. Немецкий форматировщик размещает символ после суммы с пробелом, использует точки для разделения тысяч и запятую в качестве десятичного разделителя. Французский форматировщик использует пробелы для разделения тысяч.
API Intl автоматически обрабатывает эти различия на основе указанной локали. Вам не нужно знать правила форматирования для каждой локали.
Форматирование валюты включает десятичные знаки
Форматировщики валют автоматически определяют подходящее количество десятичных знаков в зависимости от валюты. Большинство валют используют два десятичных знака для центов или эквивалентных дробей.
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
console.log(formatter.format(100));
// Вывод: "$100.00"
console.log(formatter.format(100.5));
// Вывод: "$100.50"
console.log(formatter.format(100.567));
// Вывод: "$100.57"
Форматировщик всегда отображает два десятичных знака для долларов США, добавляя нули при необходимости и округляя, если входные данные имеют большую точность.
Некоторые валюты не имеют десятичных знаков. Японская иена не имеет дробной единицы, поэтому суммы отображаются без десятичных знаков.
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'JPY'
});
console.log(formatter.format(1234.56));
// Вывод: "¥1,235"
Форматировщик округляет до ближайшего целого числа, так как суммы в иенах не включают дробные единицы. API Intl знает точность десятичных знаков для каждой валюты и применяет её автоматически.
Форматирование валюты для локали пользователя
Вместо жесткого кодирования определенной локали вы можете использовать языковые предпочтения браузера пользователя. Свойство navigator.language возвращает предпочтительную локаль пользователя.
const userLocale = navigator.language;
const formatter = new Intl.NumberFormat(userLocale, {
style: 'currency',
currency: 'USD'
});
console.log(formatter.format(1234.56));
// Вывод зависит от локали пользователя
// Для en-US: "$1,234.56"
// Для de-DE: "1.234,56 $"
// Для fr-FR: "1 234,56 $US"
Этот подход отображает суммы в валюте в соответствии с ожиданиями форматирования каждого пользователя. Немецкий пользователь видит символ после суммы с немецкими разделителями, а американский пользователь видит символ перед суммой с американскими разделителями.
Вы также можете передать весь массив navigator.languages, чтобы включить поведение резервного копирования, если предпочтение пользователя недоступно.
const formatter = new Intl.NumberFormat(navigator.languages, {
style: 'currency',
currency: 'USD'
});
console.log(formatter.format(1234.56));
API использует первую поддерживаемую локаль из массива, обеспечивая автоматическое резервное копирование.
Повторное использование форматировщиков валют
Создание нового экземпляра Intl.NumberFormat включает загрузку данных локали и обработку параметров. Если вы форматируете несколько цен с одной и той же локалью и валютой, создайте форматировщик один раз и используйте его повторно.
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
const prices = [19.99, 29.99, 49.99, 99.99];
prices.forEach(price => {
console.log(formatter.format(price));
});
// Результат:
// "$19.99"
// "$29.99"
// "$49.99"
// "$99.99"
Этот подход более эффективен, чем создание нового форматировщика для каждой цены. Разница в производительности становится заметной при форматировании массивов или списков с большим количеством значений.
Отображение цен в приложениях
Вы можете использовать форматировщики валют везде, где отображаете цены для пользователей. Это включает списки товаров, корзины покупок, страницы оформления заказа, счета и финансовые панели.
const formatter = new Intl.NumberFormat(navigator.language, {
style: 'currency',
currency: 'USD'
});
const productPrice = 29.99;
const taxAmount = 2.40;
const totalPrice = productPrice + taxAmount;
document.getElementById('product-price').textContent = formatter.format(productPrice);
document.getElementById('tax-amount').textContent = formatter.format(taxAmount);
document.getElementById('total-price').textContent = formatter.format(totalPrice);
Отформатированные строки работают как любые другие строковые значения. Вы можете вставлять их в текстовый контент, атрибуты или любой другой контекст, где отображаете информацию для пользователей.
Работа с несколькими валютами
Приложения, поддерживающие несколько валют, должны создавать отдельные форматировщики для каждой валюты. Код валюты определяет, какой символ будет отображаться, а локаль определяет, как будет форматироваться сумма.
const locale = navigator.language;
const usdFormatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'USD'
});
const eurFormatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'EUR'
});
const gbpFormatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'GBP'
});
console.log(usdFormatter.format(100));
console.log(eurFormatter.format(100));
console.log(gbpFormatter.format(100));
Каждый форматировщик отображает соответствующий символ и следует конвенциям локали пользователя для этой валюты. Это гарантирует, что цены будут как точными, так и удобочитаемыми, независимо от комбинации валюты и локали.