Диапазоны чисел в Intl.NumberFormat позволяют
единообразно форматировать промежутки значений с учётом правил
конкретной локали, включая выбор разделителей, пробелов, сокращений и
знаков тире. Это расширение стандартного числового форматирования,
которое закрывает задачу отображения интервалов без ручной конкатенации
строк и без потери локализационной корректности.
Современная реализация Intl.NumberFormat включает методы
для работы с диапазонами значений. Основная идея заключается в том, что
форматирование происходит не для двух отдельных чисел, а для логически
связанной пары значений.
Ключевые методы:
formatRange(start, end)formatRangeToParts(start, end)Оба метода учитывают настройки локали, стиль форматирования, единицы измерения и правила округления.
Метод formatRange формирует строковое представление
диапазона чисел с учётом локали.
const formatter = new Intl.NumberFormat('ru-RU');
formatter.formatRange(1, 5);
// "1–5"
В англоязычной локали результат будет аналогичен:
const formatter = new Intl.NumberFormat('en-US');
formatter.formatRange(1, 5);
// "1–5"
Однако различие проявляется не только в символе тире, но и в пробелах, правилах округления и обработке сложных чисел.
Округление применяется к каждому значению независимо, но с учётом настроек форматтера:
const formatter = new Intl.NumberFormat('en-US', {
maximumFractionDigits: 0
});
formatter.formatRange(1.2, 5.7);
// "1–6"
Оба значения проходят через одинаковые правила форматирования, что гарантирует согласованность отображения.
Если границы диапазона совпадают, результатом становится одиночное значение:
const formatter = new Intl.NumberFormat('en-US');
formatter.formatRange(5, 5);
// "5"
Это важное поведение, предотвращающее избыточное отображение интервала.
Метод formatRangeToParts возвращает не строку, а массив
структурированных частей, что позволяет точно контролировать
визуализацию диапазона.
const formatter = new Intl.NumberFormat('ru-RU');
formatter.formatRangeToParts(10, 20);
Результат:
[
{ type: 'integer', value: '10', source: 'startRange' },
{ type: 'literal', value: '–', source: 'shared' },
{ type: 'integer', value: '20', source: 'endRange' }
]
Поле source указывает происхождение части:
startRange — первая границаendRange — вторая границаshared — общие элементы (например, разделитель)Это позволяет дифференцировать стили для каждой части диапазона.
Разделитель диапазона не фиксирован и зависит от локали. В разных языковых системах используются разные символы:
–––– (с пробелами в некоторых контекстах)Несмотря на визуальную схожесть, внутренние правила могут включать:
Intl.NumberFormat поддерживает форматирование диапазонов
с единицами через style: 'unit'.
const formatter = new Intl.NumberFormat('en-US', {
style: 'unit',
unit: 'kilometer-per-hour'
});
formatter.formatRange(10, 50);
// "10–50 km/h"
Особенность заключается в том, что единица применяется к диапазону как к целому, а не к каждому числу отдельно, что обеспечивает корректное отображение.
Хотя API диапазонов существует и в Intl.DateTimeFormat,
в Intl.NumberFormat модель проще: она оперирует чистыми
числами без календарной логики.
Это приводит к различиям:
Для больших значений форматирование диапазонов учитывает группировку:
const formatter = new Intl.NumberFormat('en-US');
formatter.formatRange(1000, 5000);
// "1,000–5,000"
Группировка определяется локалью и может включать пробелы вместо запятых:
const formatter = new Intl.NumberFormat('de-DE');
formatter.formatRange(1000, 5000);
// "1.000–5.000"
Если начало больше конца, поведение не нормализуется автоматически:
formatter.formatRange(10, 5);
// "10–5"
Нормализация диапазона должна выполняться вручную при необходимости.
Некорректные значения приводят к строковым представлениям, зависящим от реализации:
formatter.formatRange(NaN, 10);
// "NaN–10"
formatter.formatRange(Infinity, 10);
// "∞–10"
Создание экземпляра Intl.NumberFormat является
относительно дорогой операцией. При частом форматировании диапазонов
используется кеширование:
const formatter = new Intl.NumberFormat('en-US');
function formatRange(a, b) {
return formatter.formatRange(a, b);
}
Это особенно важно при рендеринге списков, таблиц и UI-компонентов.
Ручная сборка строк:
`${a} - ${b}`
приводит к ряду проблем:
formatRange решает эти проблемы на уровне спецификации
ECMAScript Internationalization API.
Поддержка formatRange и formatRangeToParts
появилась в более поздних версиях спецификации ECMAScript. В старых
средах доступны только базовые методы форматирования чисел, что требует
полифиллов или ручной логики.
При отсутствии поддержки часто применяется стратегия:
Однако такое решение не эквивалентно нативному API, поскольку теряет семантическую связь диапазона.
Диапазонное форматирование применяется в интерфейсах:
В этих сценариях важно сохранять семантическую целостность интервала,
что обеспечивает Intl.NumberFormat без дополнительных
преобразований строк.