Форматирование значений в FormatJS опирается на стандарты
Intl и расширяется через слой конфигурации библиотеки
react-intl. Одним из ключевых механизмов является задание
форматтеров по умолчанию, которые применяются при вызове
formatDate, formatNumber,
formatTime, formatRelativeTime и других API
без необходимости каждый раз передавать полный набор параметров.
Базовая конфигурация форматтеров определяется на уровне провайдера
локали. Компонент IntlProvider выступает центральной
точкой, через которую прокидываются локаль, сообщения и набор
стандартных форматов. Эти значения становятся глобально доступными
внутри дерева компонентов.
Объект formats используется для предопределения наборов
правил форматирования. Он разделяется на категории:
datetimenumberrelativeTimepluralКаждая категория содержит именованные пресеты.
Пример конфигурации:
import { IntlProvider } from "react-intl";
const formats = {
date: {
short: {
year: "numeric",
month: "2-digit",
day: "2-digit"
},
long: {
year: "numeric",
month: "long",
day: "2-digit",
weekday: "long"
}
},
time: {
short: {
hour: "2-digit",
minute: "2-digit"
}
},
number: {
integer: {
maximumFractionDigits: 0
},
currencyUSD: {
style: "currency",
currency: "USD"
}
}
};
export default function App() {
return (
<IntlProvider locale="ru" messages={{}} formats={formats}>
{/* приложение */}
</IntlProvider>
);
}
После определения таких форматов становится возможным использование именованных пресетов без повторного указания параметров.
Форматтеры применяются через API formatDate,
formatNumber, formatTime или соответствующие
компоненты.
import { useIntl } from "react-intl";
function Component() {
const intl = useIntl();
const date = intl.formatDate(new Date(), {
format: "long"
});
const price = intl.formatNumber(12345.67, {
format: "currencyUSD"
});
return (
<>
<div>{date}</div>
<div>{price}</div>
</>
);
}
При указании format: "long" или
format: "currencyUSD" происходит обращение к
соответствующему объекту в IntlProvider.formats.
Механизм разрешения параметров строится по иерархии:
formatDate,
formatNumber и аналогичных функцияхIntlProvider.formatsIntl среды выполненияЛюбые параметры, переданные напрямую, перекрывают значения из пресета.
intl.formatDate(new Date(), {
format: "short",
day: "numeric" // переопределяет значение из short
});
Числовые форматтеры часто используются для валют, процентов и целых чисел. Предопределённые форматы позволяют стандартизировать отображение чисел по всему приложению.
const formats = {
number: {
percent: {
style: "percent",
minimumFractionDigits: 2
},
compact: {
notation: "compact"
}
}
};
Использование:
intl.formatNumber(0.875, { format: "percent" });
intl.formatNumber(1200000, { format: "compact" });
Категории date и time объединяют
конфигурации для отображения календарных значений. При этом используется
стандарт Intl.DateTimeFormat.
const formats = {
date: {
weekdayOnly: {
weekday: "long"
},
fullDate: {
year: "numeric",
month: "long",
day: "numeric",
weekday: "long"
}
},
time: {
withSeconds: {
hour: "2-digit",
minute: "2-digit",
second: "2-digit"
}
}
};
Применение:
intl.formatDate(new Date(), { format: "weekdayOnly" });
intl.formatTime(new Date(), { format: "withSeconds" });
Помимо IntlProvider, конфигурация может быть определена
программно через createIntl. Это используется вне
React-контекста, например в сервисах или утилитах.
import { createIntl, createIntlCache } from "react-intl";
const cache = createIntlCache();
const intl = createIntl(
{
locale: "ru",
messages: {},
formats: {
number: {
default: {
minimumFractionDigits: 2
}
}
}
},
cache
);
Полученный объект предоставляет те же методы форматирования, что и
useIntl.
В некоторых случаях требуется локальная модификация форматов без изменения глобальной конфигурации. Для этого параметры передаются напрямую в вызов форматтера.
function Price({ value }) {
const intl = useIntl();
return (
<span>
{intl.formatNumber(value, {
style: "currency",
currency: "EUR",
minimumFractionDigits: 2
})}
</span>
);
}
Такой подход имеет более высокий приоритет, чем любые предустановленные форматы.
Форматы могут комбинироваться через распространение объектов конфигурации. Это позволяет создавать базовые пресеты и расширять их для специфических сценариев.
const baseNumberFormats = {
integer: {
maximumFractionDigits: 0
}
};
const formats = {
number: {
...baseNumberFormats,
money: {
style: "currency",
currency: "USD"
}
}
};
Композиция облегчает масштабирование конфигурации в крупных приложениях.
Если указанный формат отсутствует в formats, происходит
игнорирование имени пресета и используется набор параметров, переданных
явно или значения по умолчанию Intl.
intl.formatDate(new Date(), {
format: "nonExistingFormat",
year: "numeric"
});
В таком случае nonExistingFormat не применяется, но
остальные параметры сохраняются.
Форматтеры тесно связаны с текущей локалью. Один и тот же набор
форматов может давать разные результаты в зависимости от значения
locale, переданного в IntlProvider.
<IntlProvider locale="en">
<IntlProvider locale="ru">
Различия проявляются в порядке компонентов даты, разделителях чисел, обозначении валют и других региональных правилах.
FormatJS предоставляет компоненты-обёртки, которые также поддерживают именованные форматы.
import { FormattedDate, FormattedNumber } from "react-intl";
<FormattedDate value={new Date()} format="long" />
<FormattedNumber value={1000} format="integer" />
Компоненты используют те же правила приоритета, что и программный API.
Хотя форматтеры по умолчанию чаще используются для чисел и дат, они также могут косвенно применяться внутри ICU сообщений через параметры.
const messages = {
balance: "Баланс: {value, number, currencyUSD}"
};
В данном случае currencyUSD берётся из конфигурации
formats.number.
Создание форматтеров связано с использованием Intl
объектов, которые могут быть затратными при частом создании. FormatJS
использует внутренний кеш через createIntlCache, уменьшая
количество повторных инстанциаций форматтеров.
const cache = createIntlCache();
Повторное использование кеша снижает нагрузку при рендеринге списков и частых обновлениях UI.
Некорректные ключи в formats не приводят к исключению,
но могут вызывать игнорирование конфигурации. Частая проблема связана с
несоответствием структуры:
Intl.DateTimeFormatПриоритет всегда отдаётся валидным параметрам Intl среды
выполнения, а не произвольным полям конфигурации.