Базовое форматирование числовых значений

В основе работы с числами в экосистеме FormatJS лежит стандарт Intl.NumberFormat, поверх которого библиотека предоставляет унифицированные утилиты для интернационализации. Основная идея — отделить бизнес-логику от локализованного представления данных, обеспечив предсказуемое форматирование чисел для разных языков и регионов.

FormatJS не изобретает собственный механизм форматирования чисел, а систематизирует использование ECMAScript Internationalization API, добавляя слой декларативности и интеграции с компонентами и сообщениями.


Базовый механизм форматирования чисел

Ключевой инструмент — Intl.NumberFormat, который позволяет преобразовывать числовые значения в локализованные строки.

const formatter = new Intl.NumberFormat('en-US');

formatter.format(1234567.89);
// "1,234,567.89"

При смене локали меняется и представление:

const formatter = new Intl.NumberFormat('de-DE');

formatter.format(1234567.89);
// "1.234.567,89"

FormatJS использует этот механизм как фундамент, но добавляет уровень абстракции для переиспользования форматов в приложениях.


Использование чисел через FormatJS API

В FormatJS числовое форматирование обычно происходит через функции formatNumber или через компоненты в React-интеграции.

formatNumber как базовая функция

import { formatNumber } from 'react-intl';

formatNumber(12345, {
  locale: 'en-US'
});

Функция принимает значение и объект параметров форматирования, возвращая локализованную строку.


Форматы чисел: основные категории

Целые числа

Для целых значений чаще всего используется формат без дробной части.

const formatter = new Intl.NumberFormat('en-US', {
  maximumFractionDigits: 0
});

formatter.format(1234.56);
// "1,235"

В FormatJS это эквивалентно:

formatNumber(1234.56, {
  maximumFractionDigits: 0
});

Числа с фиксированной точностью

При работе с финансовыми или инженерными данными важно фиксировать количество знаков после запятой.

const formatter = new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

formatter.format(12);
// "12.00"
formatNumber(12, {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

Автоматическая точность

Если точность не фиксируется, форматтер сам адаптирует вывод:

const formatter = new Intl.NumberFormat('en-US');

formatter.format(10);
// "10"

formatter.format(10.5);
// "10.5"

formatter.format(10.5678);
// "10.568"

Группировка разрядов

Разделение числа на группы — важная часть локализации.

const formatter = new Intl.NumberFormat('en-US', {
  useGrouping: true
});

formatter.format(1000000);
// "1,000,000"

В некоторых локалях формат отличается:

new Intl.NumberFormat('fr-FR').format(1000000);
// "1 000 000"

FormatJS наследует это поведение без изменений, обеспечивая консистентность между сервером и клиентом.


Минимальные и максимальные границы отображения

Ограничение количества цифр

new Intl.NumberFormat('en-US', {
  minimumIntegerDigits: 5
}).format(42);
// "00042"

Контроль округления

new Intl.NumberFormat('en-US', {
  maximumFractionDigits: 1
}).format(12.345);
// "12.3"

Округление происходит по правилам IEEE 754 и спецификации ECMAScript.


Отображение процентов

Процентный формат — один из наиболее частых сценариев локализации.

new Intl.NumberFormat('en-US', {
  style: 'percent'
}).format(0.25);
// "25%"

FormatJS позволяет использовать тот же стиль через параметры:

formatNumber(0.25, {
  style: 'percent'
});

Важно учитывать, что значение интерпретируется как доля единицы, а не как уже умноженный процент.


Валютное форматирование

Хотя валюты относятся к более сложной теме, базовая логика входит в числовое форматирование.

new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(1234.5);
// "$1,234.50"

FormatJS:

formatNumber(1234.5, {
  style: 'currency',
  currency: 'USD'
});

Локаль влияет не только на порядок символов, но и на расположение обозначения валюты.


Компактное представление чисел

Для больших значений используется компактный стиль:

new Intl.NumberFormat('en-US', {
  notation: 'compact'
}).format(1500000);
// "1.5M"

В FormatJS:

formatNumber(1500000, {
  notation: 'compact'
});

Поддерживаются разные уровни компактности:

  • short: 1K, 1M
  • long: 1 thousand, 1 million

Настройка локали в FormatJS

FormatJS централизует управление локалью через provider (в React) или через конфигурацию intl.

Пример базового использования:

import { IntlProvider, FormattedNumber } from 'react-intl';

<IntlProvider locale="en">
  <FormattedNumber value={1234567.89} />
</IntlProvider>

Компонент автоматически использует локаль контекста.


Форматирование через React-компоненты

FormattedNumber как декларативный слой

<FormattedNumber value={1000} />

Эквивалент императивного вызова formatNumber, но встроен в JSX и автоматически реагирует на смену локали.

Передача параметров форматирования

<FormattedNumber
  value={0.85}
  style="percent"
  minimumFractionDigits={0}
/>

Переиспользуемые числовые форматы

FormatJS поддерживает именованные форматы, позволяя централизовать правила отображения.

const messages = {
  price: {
    style: 'currency',
    currency: 'USD'
  }
};

Использование:

formatNumber(99.99, messages.price);

Это снижает дублирование и повышает согласованность интерфейса.


Особенности округления и точности

Форматирование чисел в FormatJS опирается на правила ICU, что означает:

  • округление “half-even” в некоторых режимах
  • предсказуемое поведение при дробных значениях
  • зависимость от локали при отображении разделителей

Пример:

new Intl.NumberFormat('en-US', {
  maximumFractionDigits: 2
}).format(1.005);
// "1.01" (в зависимости от реализации движка)

Производительность форматирования

Создание Intl.NumberFormat — относительно дорогая операция. В реальных приложениях FormatJS предполагает переиспользование форматтеров:

const numberFormatter = new Intl.NumberFormat('en-US');

numberFormatter.format(1000);
numberFormatter.format(2000);

В React-интеграции кеширование выполняется автоматически через контекст IntlProvider, что снижает нагрузку при повторных рендерах.


Обработка некорректных значений

Числовой форматтер ожидает корректные числовые входы. При передаче:

  • NaN → строка "NaN"
  • Infinity"∞" или локализованная форма
  • строк → попытка приведения к числу
new Intl.NumberFormat('en-US').format(NaN);
// "NaN"

FormatJS не скрывает ошибки, а сохраняет поведение стандарта ECMAScript.


Согласованность между сервером и клиентом

Одной из ключевых задач FormatJS является предотвращение расхождений между серверным и клиентским рендерингом.

Для чисел это означает:

  • одинаковые настройки локали
  • идентичные параметры форматирования
  • отсутствие ручного форматирования строк

При соблюдении этих условий результат formatNumber будет стабильным на всех этапах выполнения приложения.