Интернационализация в современных фронтенд-приложениях опирается на два слоя: прикладной (React-логика отображения) и платформенный (возможности браузера и ECMAScript). В браузерной среде ключевую роль играет Intl API — встроенный набор объектов для форматирования дат, чисел, валют, сравнения строк и работы с локалями. Его применение в React позволяет отказаться от внешних тяжёлых библиотек в части базового форматирования и перенести часть логики в стандарт среды выполнения.
React, как компонентная модель отображения, не предоставляет встроенной системы i18n. Он лишь реагирует на изменение состояния и свойств, а значит вся интернационализация реализуется через композицию: форматтеры, контекст локали, утилиты и мемоизированные вычисления.
Intl API предоставляет набор конструкторов, каждый из которых решает конкретный класс задач.
Intl.NumberFormat используется для отображения чисел с
учётом локали:
const formatter = new Intl.NumberFormat('ru-RU');
formatter.format(1234567.89);
// "1 234 567,89"
Для валют:
const usd = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
usd.format(99.99);
// "$99.99"
Ключевая особенность — отсутствие необходимости ручного управления форматами: локаль и правила кодируются в движке.
Intl.DateTimeFormat обеспечивает локализованное
отображение дат.
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
formatter.format(new Date());
// "26 мая 2026 г."
Поддерживаются различные уровни детализации:
shortmediumlongfullТакже доступны часы, минуты, секунды, часовые пояса.
Intl.RelativeTimeFormat применяется для интерфейсов с
динамическими временными метками:
const rtf = new Intl.RelativeTimeFormat('ru', { numeric: 'auto' });
rtf.format(-1, 'day');
// "вчера"
rtf.format(3, 'hour');
// "через 3 часа"
Этот API особенно полезен в лентах активности, уведомлениях и чатах.
Intl.Collator обеспечивает корректную сортировку строк с
учётом языка:
const collator = new Intl.Collator('ru', { sensitivity: 'base' });
['ёж', 'яблоко', 'ель'].sort(collator.compare);
Без него сортировка по Unicode-кодам приводит к некорректным результатам для многих языков.
Создание экземпляров Intl.* — операция относительно
дорогая. В React-компонентах при каждом рендере это может привести к
лишним вычислениям.
Базовый подход — мемоизация:
const formatter = useMemo(() => {
return new Intl.NumberFormat('ru-RU');
}, []);
Такой подход фиксирует форматтер на уровне жизненного цикла компонента.
Часто форматирование выносится за пределы компонентов:
export const formatPrice = (value, locale) => {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'USD'
}).format(value);
};
Это упрощает тестирование и снижает связность UI.
В многоязычных приложениях используется глобальный контекст:
const LocaleContext = createContext('en-US');
Компоненты получают текущую локаль и используют её для создания форматтеров.
const locale = useContext(LocaleContext);
const formatter = useMemo(() => {
return new Intl.NumberFormat(locale);
}, [locale]);
Изменение локали автоматически приводит к пересозданию форматтеров и обновлению интерфейса.
Интерфейсы часто содержат числа, которые должны адаптироваться к региону:
function Price({ value }) {
const locale = useContext(LocaleContext);
const formatted = useMemo(() => {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: 'EUR'
}).format(value);
}, [value, locale]);
return <span>{formatted}</span>;
}
function DateLabel({ date }) {
const locale = useContext(LocaleContext);
const formatted = useMemo(() => {
return new Intl.DateTimeFormat(locale, {
year: 'numeric',
month: 'short',
day: 'numeric'
}).format(new Date(date));
}, [date, locale]);
return <time>{formatted}</time>;
}
Для обновления относительного времени требуется периодический пересчёт:
function useRelativeTime(date) {
const locale = useContext(LocaleContext);
const [, forceUpdate] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
forceUpdate(x => x + 1);
}, 60000);
return () => clearInterval(interval);
}, []);
return useMemo(() => {
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
const diff = Math.round((new Date(date) - new Date()) / 60000);
return rtf.format(diff, 'minute');
}, [date, locale]);
}
Intl-объекты зависят от локали и опций. Это делает их идеальными кандидатами для кэширования:
const cache = new Map();
function getNumberFormatter(locale, options) {
const key = locale + JSON.stringify(options);
if (!cache.has(key)) {
cache.set(key, new Intl.NumberFormat(locale, options));
}
return cache.get(key);
}
Такой подход уменьшает накладные расходы при частых рендерах списков.
В больших таблицах или списках важно избегать повторного создания форматтеров на каждый элемент:
const formatter = useMemo(() => {
return new Intl.NumberFormat(locale);
}, [locale]);
return items.map(item => (
<div key={item.id}>
{formatter.format(item.value)}
</div>
));
При SSR (Server-Side Rendering) возникают особенности:
Стратегия стабилизации:
const locale = req.headers['accept-language'] || 'en-US';
Intl API решает форматирование, но не покрывает:
В React это приводит к разделению ответственности:
const messages = {
en: { items: 'Items' },
ru: { items: 'Элементы' }
};
const plural = new Intl.PluralRules('ru');
const rule = plural.select(5);
// "many"
Используется для выбора правильной формы слова:
const forms = ['элемент', 'элемента', 'элементов'];
function formatItems(count) {
const rule = plural.select(count);
const index = {
one: 0,
few: 1,
many: 2,
other: 2
}[rule];
return `${count} ${forms[index]}`;
}
В React часто выделяются специализированные компоненты:
FormattedNumberFormattedDateFormattedCurrencyИх задача — скрыть детали Intl API:
function FormattedCurrency({ value, currency }) {
const locale = useContext(LocaleContext);
const formatted = useMemo(() => {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency
}).format(value);
}, [value, currency, locale]);
return <span>{formatted}</span>;
}
Несмотря на широкие возможности, существуют ограничения:
Это определяет роль Intl API как низкоуровневого слоя, поверх которого строятся i18n-фреймворки и архитектуры приложений на базе React.