Экосистема FormatJS опирается на стандарты
ECMA-402 (Intl API), расширяя их средствами форматирования
сообщений и локализации. Числовые стили в этом контексте охватывают
преобразование чисел в человекочитаемые строки с учётом локали, единиц
измерения, валют и правил округления.
Основой служит Intl.NumberFormat, который используется
напрямую или через обёртки FormatJS.
const formatter = new Intl.NumberFormat('ru-RU');
formatter.format(1234567.89);
// "1 234 567,89"
FormatJS в react-intl предоставляет компонент и API
FormattedNumber, который инкапсулирует этот механизм:
import { FormattedNumber } from 'react-intl';
<FormattedNumber value={1234567.89} />
Поведение зависит от текущей локали провайдера
IntlProvider.
Intl.NumberFormat поддерживает несколько ключевых
режимов форматирования через параметр style.
Используется по умолчанию, предназначен для отображения обычных чисел.
new Intl.NumberFormat('ru-RU', {
style: 'decimal'
}).format(10000.5);
// "10 000,5"
В FormatJS:
<FormattedNumber value={10000.5} style="decimal" />
Форматирование с учётом валюты включает код валюты ISO 4217 и локальные правила отображения.
new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB'
}).format(1999.99);
// "1 999,99 ₽"
Особенности валютного форматирования:
В FormatJS:
<FormattedNumber value={1999.99} style="currency" currency="RUB" />
Для динамических валют используется передача параметров:
const currency = 'USD';
new Intl.NumberFormat('en-US', {
style: 'currency',
currency
}).format(120);
// "$120.00"
Процентное представление предполагает умножение значения на 100 и
добавление символа % с учётом локали.
new Intl.NumberFormat('ru-RU', {
style: 'percent'
}).format(0.25);
// "25 %"
В FormatJS:
<FormattedNumber value={0.25} style="percent" />
Важно учитывать, что входное значение всегда нормализовано (0–1), а не 0–100.
Форматирование чисел включает управление точностью через параметры:
minimumFractionDigitsmaximumFractionDigitsminimumIntegerDigitsroundingMode (в новых реализациях)new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 4
}).format(12.3);
// "12.30"
FormatJS передаёт эти параметры через пропсы:
<FormattedNumber
value={12.3}
minimumFractionDigits={2}
maximumFractionDigits={4}
/>
Особое значение имеет округление:
new Intl.NumberFormat('en-US', {
maximumFractionDigits: 0
}).format(12.9);
// "13"
Современный Intl.NumberFormat поддерживает стиль
unit, который применяется для физических и прикладных
единиц.
new Intl.NumberFormat('ru-RU', {
style: 'unit',
unit: 'kilometer-per-hour'
}).format(120);
// "120 км/ч"
Поддерживаемые единицы стандартизированы: скорость, масса, длина, энергия и др.
В FormatJS:
<FormattedNumber value={120} style="unit" unit="kilometer-per-hour" />
Особенности:
Текстовые стили в FormatJS связаны с ICU Message Format, который
используется в react-intl через
FormattedMessage и API formatMessage. Основные
механизмы включают интерполяцию, множественные формы, выбор вариантов и
вложенные структуры.
ICU-сообщения позволяют внедрять переменные в текст:
const messages = {
greeting: 'Привет, {name}'
};
Использование:
<FormattedMessage id="greeting" values={{ name: 'Алексей' }} />
Интерполяция поддерживает любые типы данных, включая числа и даты, которые форматируются автоматически через Intl API.
Одной из ключевых возможностей является автоматическая обработка множественных форм.
const messages = {
items: 'В корзине {count, plural, one {# товар} few {# товара} many {# товаров} other {# товара}}'
};
Использование:
<FormattedMessage id="items" values={{ count: 5 }} />
Особенности:
ru, en,
ar и др.);Intl.PluralRules под капотом;one, few,
many, other.Пример различий:
// ru-RU
1 товар
2 товара
5 товаров
// en-US
1 item
2 items
5 items
Для порядковых форм используется отдельный механизм:
const messages = {
rank: '{place, selectordinal, one {#-й} two {#-й} few {#-й} other {#-й}}'
};
<FormattedMessage id="rank" values={{ place: 2 }} />
Под капотом применяется Intl.PluralRules с типом
ordinal.
Механизм select позволяет строить условные конструкции
на основе строковых значений.
const messages = {
status: '{gender, select, male {Он пришёл} female {Она пришла} other {Они пришли}}'
};
Использование:
<FormattedMessage id="status" values={{ gender: 'female' }} />
Поддерживается любое количество вариантов, включая other
как обязательный fallback.
ICU-синтаксис допускает композицию конструкций:
const messages = {
inbox:
'У {name} {count, plural, one {# новое сообщение} few {# новых сообщения} many {# новых сообщений} other {# сообщения}}'
};
<FormattedMessage
id="inbox"
values={{ name: 'Мария', count: 3 }}
/>
Вложенность обеспечивает гибкую генерацию текста без необходимости ручной сборки строк в коде.
Числа внутри ICU-сообщений автоматически форматируются через Intl,
если используется FormattedNumber или передаются через
values.
const messages = {
balance: 'Баланс: {amount, number, currency}'
};
<FormattedMessage
id="balance"
values={{ amount: 1234.56 }}
/>
При необходимости можно управлять стилем:
const messages = {
balance: 'Баланс: {amount, number, ::currency/RUB}'
};
Хотя это выходит за рамки числовых стилей, в ICU оно относится к текстовым форматам:
const messages = {
date: 'Дата: {ts, date, long}'
};
<FormattedMessage
id="date"
values={{ ts: Date.now() }}
/>
Поддерживаются стили:
shortmediumlongfullFormatJS поддерживает разметку внутри сообщений через функцию
values, где значения могут быть функциями, возвращающими
JSX.
const messages = {
warning: 'Согласие с {terms} обязательно'
};
<FormattedMessage
id="warning"
values={{
terms: (chunks) => <a href="/terms">{chunks}</a>
}}
/>
Такой механизм позволяет внедрять семантическую разметку без нарушения локализационной структуры строки.
ICU-синтаксис требует экранирования фигурных скобок:
const messages = {
example: "Символы '{' и '}' используются для параметров"
};
Также поддерживается защита от некорректной интерполяции за счёт строгого парсинга сообщений.
В реальных сценариях числовые и текстовые стили используются совместно:
const messages = {
report:
'{name} получил {score, number, ::percent} успешности и {tasks, plural, one {# задачу} few {# задачи} many {# задач} other {# задачи}}'
};
<FormattedMessage
id="report"
values={{
name: 'Иван',
score: 0.87,
tasks: 5
}}
/>
Такая комбинация демонстрирует ключевую идею FormatJS: единая декларативная система для локализованного представления данных разных типов.