Форматирование чисел в JavaScript через международный API
Intl основано на локализации представления числовых
значений. Одним из ключевых аспектов локализации является отображение
разделителей: тысячного (grouping separator) и десятичного (decimal
separator). Эти символы зависят от языкового и регионального контекста и
не являются универсальными.
Разные культуры используют различные соглашения для визуального разделения чисел:
в англоязычной локали (en-US):
,.в большинстве европейских локалей (de-DE, fr-FR):
,в русской локали (ru-RU):
,Таким образом, одно и то же число может выглядеть по-разному:
1234567.89 →
1,234,567.89 (en-US)1 234 567,89 (ru-RU)1.234.567,89 (de-DE)Intl.NumberFormatОсновной инструмент форматирования чисел — конструктор
Intl.NumberFormat.
const formatter = new Intl.NumberFormat('en-US');
formatter.format(1234567.89);
// "1,234,567.89"
При смене локали меняются и символы разделителей:
const formatterRU = new Intl.NumberFormat('ru-RU');
formatterRU.format(1234567.89);
// "1 234 567,89"
Группировка разрядов регулируется опцией
useGrouping.
const formatter = new Intl.NumberFormat('en-US', {
useGrouping: true
});
formatter.format(1000000);
// "1,000,000"
Отключение группировки:
const formatter = new Intl.NumberFormat('en-US', {
useGrouping: false
});
formatter.format(1000000);
// "1000000"
Типы группировки зависят от локали:
const formatter = new Intl.NumberFormat('en-IN');
formatter.format(123456789);
// "12,34,56,789"
Десятичный разделитель определяется локалью и не задаётся напрямую. Однако управление количеством дробных знаков влияет на итоговое представление числа.
const formatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
formatter.format(12.5);
// "12.50"
Если дробная часть отсутствует:
formatter.format(12);
// "12.00"
Изменение числа знаков после запятой может приводить к округлению:
const formatter = new Intl.NumberFormat('en-US', {
maximumFractionDigits: 2
});
formatter.format(1.239);
// "1.24"
Локаль определяет только символ разделителя, но не правило округления.
formatToPartsДля точного понимания структуры числа используется метод
formatToParts, который позволяет увидеть отдельные
компоненты: цифры и разделители.
const formatter = new Intl.NumberFormat('en-US');
formatter.formatToParts(1234.56);
Результат:
[
{ type: 'integer', value: '1' },
{ type: 'group', value: ',' },
{ type: 'integer', value: '234' },
{ type: 'decimal', value: '.' },
{ type: 'fraction', value: '56' }
]
Здесь явно выделяются:
group — тысячный разделительdecimal — десятичный разделительinteger — целая частьfraction — дробная частьВыбор символов определяется таблицами Unicode CLDR, которые используются движком JavaScript для интернационализации.
Пример различий:
new Intl.NumberFormat('en-US').format(1000);
// "1,000"
new Intl.NumberFormat('de-DE').format(1000);
// "1.000"
new Intl.NumberFormat('ru-RU').format(1000);
// "1 000"
В ряде локалей используется не обычный пробел, а неразрывный пробел или узкий неразрывный пробел.
const formatter = new Intl.NumberFormat('fr-FR');
formatter.format(1000000);
Результат визуально выглядит как:
1 000 000
Символ между группами — узкий неразрывный пробел (U+202F), что предотвращает разрыв числа при переносе строки.
Разделители используются не только в стандартном числовом формате
(style: "decimal"), но и в других стилях:
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(1234.56);
// "$1,234.56"
new Intl.NumberFormat('en-US', {
style: 'percent'
}).format(0.1234);
// "12%"
Во всех случаях система разделителей остаётся локализованной.
numberingSystemПомимо разделителей, форматирование зависит от системы счисления:
new Intl.NumberFormat('en-US', {
numberingSystem: 'latn'
}).format(1234567);
В некоторых системах используются альтернативные цифры, но логика разделителей сохраняется.
Сравнение одной и той же величины:
| Локаль | Результат |
|---|---|
| en-US | 1,234,567.89 |
| de-DE | 1.234.567,89 |
| ru-RU | 1 234 567,89 |
| fr-FR | 1 234 567,89 |
Различие касается только символов разделителей и пробельных норм, сама числовая величина остаётся неизменной.
Intl.NumberFormat не работает с уже отформатированными
строками, а оперирует числовыми значениями. Это гарантирует корректное
применение разделителей независимо от входного представления:
new Intl.NumberFormat('ru-RU').format(1000.5);
// "1 000,5"
Передача строки не рассматривается как форматируемое число:
new Intl.NumberFormat('ru-RU').format("1000.5");
// "1 000,5" (строка приводится к числу)
При увеличении разрядности сохраняется та же логика группировки:
new Intl.NumberFormat('en-US').format(9876543210123);
// "9,876,543,210,123"
Локаль продолжает определять только символы разделителей, а не алгоритм группировки.
Локализованные разделители используются в интерфейсах, где важна читаемость чисел:
Единообразие достигается за счёт применения
Intl.NumberFormat вместо ручного форматирования через
toLocaleString или строковые манипуляции.