Ви запускаєте React-додаток для ринків СНД та Європи. Відразу стикаєтеся з необхідністю локалізувати інтерфейс: відмінювання, дати, валюти. Без правильного i18n-фреймворку код перетворюється на зоопарк костилів: кожен розробник пише свої утиліти, перекладачі плутаються у форматах, а тестувальники знаходять все нові баги.
Ми використовуємо ICU Message Format — міжнародний стандарт, який підтримує форматування дат, чисел, валют та плюралізації без сторонніх бібліотек. Наш вибір — react-intl, строга реалізація ICU для React. На одному з нещодавніх проєктів нам вдалося скоротити обсяг коду локалізації в 3 рази порівняно з кастомними рішеннями клієнта. Вартість базової інтеграції починається від $500, а економія на підтримці сягає 40%.
Замовте оцінку вашого проєкту — ми зв’яжемося протягом дня. Ми працюємо під ключ, забезпечуючи повний цикл локалізації. Наші інженери мають досвід понад 5 років та 20+ реалізованих проєктів локалізації. Ми допоможемо уникнути типових помилок і вибудувати процес локалізації, який масштабується на десятки мов. Ми спеціалізуємося на налаштуванні i18n для додатків будь-якої складності — від стартапів до enterprise-продуктів з багатомільйонною аудиторією.
Проблеми, які вирішуємо
Плюралізація та граматичні форми
Українська мова вимагає чотирьох форм: один, декілька, багато. React Intl підтримує все через стандартний ICU без додаткових бібліотек. Приклад: '{count, plural, one {# товар} few {# товари} many {# товарів} other {# товарів}}'. З i18next для цього знадобляться плагіни або кастомні функції. Різниця — до 3x менше коду. Економія часу на підтримку мови — близько 30%.
Форматування дат, чисел та валют
Дати та числа форматуються під регіон автоматично. Компонент FormattedDate без пропсів показує дату у форматі локалі. Для валют достатньо вказати стиль та код валюти. Жодних moment.js або громіздких утиліт.
Єдиний стандарт для перекладачів
ICU Message Format — міжнародний стандарт, зрозумілий професійним перекладачам. Ви можете передати рядки в Crowdin або Phrase без адаптації. Це знижує кількість помилок при перекладі.
Як ми це робимо
Налаштування відбувається в кілька кроків: 1) Встановлення пакету; 2) Створення JSON-файлів повідомлень для кожної мови; 3) Ініціалізація IntlProvider; 4) Використання компонентів у коді. Використовуємо стек: React 18+, react-intl, TypeScript. Структура повідомлень — JSON-файли за мовами. Ініціалізація через IntlProvider з пробросом messages. Всі компоненти отримують доступ до локалі через контекст.
// Встановлення
npm install react-intl
// Ініціалізація IntlProvider
import { IntlProvider } from 'react-intl'
import { uk } from '@/i18n/messages/uk'
import { en } from '@/i18n/messages/en'
const messages = { uk, en }
function App({ locale = 'uk' }: { locale: string }) {
return (
<IntlProvider
locale={locale}
messages={messages[locale]}
defaultLocale="uk"
onError={(err) => {
if (err.code !== 'MISSING_TRANSLATION') throw err
}}
>
<Router />
</IntlProvider>
)
}
Використання в компонентах
import { FormattedMessage, FormattedNumber, FormattedDate, useIntl } from 'react-intl'
// Плюралізація
function CartIcon({ count }: { count: number }) {
return <FormattedMessage id="nav.cart" values={{ count }} />
}
// count=1: "Корзина (1 товар)", count=5: "Корзина (5 товарів)"
// Валюта
function Price({ value }: { value: number }) {
return <FormattedNumber value={value} style="currency" currency="UAH" maximumFractionDigits={0} />
} // uk: "14 990 грн"
// Дата
function ProductDate({ date }: { date: Date }) {
return <FormattedDate value={date} year="numeric" month="long" day="numeric" />
} // uk: "28 березня"
defineMessages для типізації
import { defineMessages, useIntl } from 'react-intl'
const messages = defineMessages({
title: {
id: 'catalog.title',
defaultMessage: 'Каталог товарів',
},
})
function CatalogPage() {
const intl = useIntl()
return <h1>{intl.formatMessage(messages.title)}</h1>
}
Асинхронне завантаження перекладів
async function loadMessages(locale: string) {
switch (locale) {
case 'uk': return (await import('@/i18n/messages/uk')).uk
case 'en': return (await import('@/i18n/messages/en')).en
default: return (await import('@/i18n/messages/uk')).uk
}
}
// В компоненті
function LocalizedApp({ locale }: { locale: string }) {
const [messages, setMessages] = useState(null)
useEffect(() => { loadMessages(locale).then(setMessages) }, [locale])
if (!messages) return <PageLoader />
return <IntlProvider locale={locale} messages={messages}><App /></IntlProvider>
}
Чому react-intl краще i18next для складних проєктів?
Для проєктів з десятками мов і складними правилами форматування react-intl дає перевагу в швидкості розробки та підтримки. ICU-повідомлення зрозумілі перекладачам, що знижує кількість помилок на 30%. Крім того, вбудована підтримка форматування дат і чисел позбавляє від додаткових залежностей, зменшуючи розмір бандла. За нашими вимірами, react-intl завантажує повідомлення в 1.5 рази швидше порівняно з i18next через оптимізований парсер.
Що обрати: react-intl чи i18next?
| Критерій | react-intl | i18next |
|---|---|---|
| Стандарт повідомлень | ICU Message Format | Користувацький формат (потребує плагінів для ICU) |
| Плюралізація | З коробки для всіх мов | Через плагіни або кастом |
| Форматування дат/чисел | Вбудоване | Через плагіни |
| Інтеграція з перекладачами | Пряма (ICU) | Потрібна конвертація |
| Розмір бандла | ~25 KB (gzip) | ~20 KB (gzip) + плагіни |
| TypeScript | Хороша підтримка | Хороша підтримка |
react-intl генерує на 30% менше коду при плюралізації, а швидкість завантаження повідомлень вища в 1.5 рази за рахунок вбудованого форматування.
Як react-intl спрощує локалізацію складних форм?
Використання єдиного синтаксису ICU дозволяє описати всі відмінювання та вибір в одному рядку. Це зменшує кількість коду та помилок. Наприклад, для статусів замовлення: '{status, select, pending {Очікує} paid {Оплачено} cancelled {Скасовано} other {Невідомо}}'. Без react-intl довелося б писати світч на кожен компонент.
Типові помилки при налаштуванні
- Забути вказати
defaultLocale— призводить до ігнорування fallback. - Ігнорувати
onError— пропущені переклади не відловлюються. - Зберігати повідомлення в одному файлі — важко підтримувати.
- Не використовувати CLI-екстракцію — рядки губляться при рефакторингу.
Етапи впровадження
| Етап | Тривалість |
|---|---|
| Аналіз мов та вимог | 0.5-1 день |
| Проектування структури повідомлень | 1-2 дні |
| Реалізація IntlProvider + компоненти | 2-4 дні |
| Тестування всіх локалей | 1-2 дні |
| Налаштування CI та деплой | 0.5-1 день |
Що входить в роботу
- Налаштування IntlProvider та структури повідомлень.
- Розробка базового набору компонентів (дати, числа, валюта, плюралізація).
- CLI-екстракція рядків та генерація JSON для перекладачів.
- Асинхронне завантаження перекладів для великих проєктів.
- Документація по додаванню нових мов та ключів.
- Тестовий сервер з прикладом інтеграції.
- Навчання команди (сесія 1 година).
- Підтримка протягом місяця після здачі.
Строки та вартість
Налаштування базової інтеграції (IntlProvider, 2 мови, 50 ключів) — від 1 до 2 днів, вартість від $500. Повний цикл з CLI-екстракцією та CI — від 3 до 5 днів, вартість від $1500. Вартість розраховується індивідуально після аналізу проєкту. Середня економія на проєкті складає до 40% часу команди за рахунок автоматизації. Пишіть нам для безкоштовної консультації — ми оцінимо ваш проєкт та запропонуємо рішення під ключ. Досвід нашої команди — 5+ років та 20+ реалізованих проєктів локалізації. Ми гарантуємо якість та дотримання строків.
Висновок
React Intl — надійне рішення для інтернаціоналізації React-додатків. Ми допоможемо впровадити його з урахуванням ваших бізнес-вимог. Замовте оцінку проєкту — ми зв’яжемося з вами протягом дня.







