Skip to main content
Назад к блогу
4 мин чтения

next-intl vs next-i18next: стоимость миграции, которую я реально заплатил

Я мигрировал продакшн Next.js сайт с next-i18next на next-intl. Почему, сколько заняло, что сломалось и стоило ли оно того.

next.jsi18nperformance

Этот сайт — dimaver6.com — начинался на next-i18next. Я мигрировал его на next-intl за один выходной. Миграция была прямолинейной. Решение мигрировать — нет.

Почему переключился

1. Поддержка App Router

next-i18next был собран для Pages Router. Когда Next.js перешёл на App Router, next-i18next добавил поддержку, но она ощущалась как прикрученная сбоку. Server Components требовали обходных путей.

next-intl был спроектирован для App Router с самого начала. getTranslations() работает естественно в Server Components, лейаутах и generateMetadata. Без обходных путей, без прокидывания пропсов.

2. Типобезопасность

next-intl поддерживает типизированные ключи переводов из коробки. Если я ссылаюсь на t('Navigation.bog') вместо t('Navigation.blog') — TypeScript ловит на этапе сборки. next-i18next требовал дополнительной настройки для того же уровня типобезопасности.

3. Интеграция роутинга

next-intl включает слой роутинга (createNavigation, createMiddleware), который обрабатывает определение локали, роутинг с префиксами и генерацию hreflang. С next-i18next я управлял роутингом локалей вручную — кастомный middleware, ручные hreflang-теги, отдельный скрипт определения локали.

next-intl свернул 4 файла кастомного кода роутинга в 2 файла конфигурации.

Миграция

Шаг 1: Установка и настройка (30 минут)

Создал i18n/config.ts, i18n/request.ts и i18n/navigation.ts.

Шаг 2: Формат файлов переводов (0 минут)

Обе библиотеки используют JSON с одинаковой структурой. Файлы messages/*.json заработали как есть. Никакого переформатирования.

Шаг 3: Замена middleware (45 минут)

60 строк кастомного middleware → 6 строк с createMiddleware от next-intl.

Шаг 4: Обновление Server Components (2 часа)

Самая большая часть. Каждый Server Component с переводами нуждался в обновлении:

// До: useTranslation (клиентский хук)
// После: getTranslations (асинхронная серверная функция)
import { getTranslations } from 'next-intl/server';

export default async function MyPage() {
  const t = await getTranslations('MyNamespace');
  return <h1>{t('title')}</h1>;
}

~25 компонентов. Большинство — механический find-and-replace.

Шаг 5: Обновление Client Components (1 час)

~10 компонентов: useTranslationuseTranslations.

Замена ручных локализованных URL на Link из @/i18n/navigation. ~15 мест.

Шаг 7: Обновление метаданных (30 минут)

generateMetadata с getTranslations — чисто и естественно.

Общее время миграции: ~5 часов

Что сломалось

1. Регистр неймспейсов

next-i18next использует lowercase (common). Я переключился на PascalCase (Common). Пропустил два места — пустые строки в русской локали. Поймал TypeScript.

2. Синтаксис интерполяции

Обе используют {variable}, но next-i18next также поддерживал {{variable}}. Три строки с двойными фигурными скобками рендерились как литеральный текст. Быстрый regex-фикс.

3. Правила множественного числа

next-i18next: key_one, key_other. next-intl: ICU формат {count, plural, one {# item} other {# items}}. 4 строки с множественным числом. 15 минут на конвертацию.

4. Переключатель языка

Компонент использовал i18next.changeLanguage(). next-intl переключает через навигацию (редирект с другим префиксом локали). Нужен был рерайт компонента.

Честное сравнение

next-intlnext-i18next
App RouterНативная, первоклассная поддержкаДобавлена позже, ощущается прикрученной
Server ComponentsgetTranslations() — чистый asyncТребует обходных путей
ТипобезопасностьВстроеннаяВозможна, но требует ручной настройки
РоутингВключён (middleware, Link, redirect)BYO или ограниченный роутинг
Формат переводовJSONJSON (формат i18next)
Множественное числоICU MessageFormatФормат i18next (_one, _other)
ЭкосистемаМеньше, специфична для Next.jsОгромная (экосистема i18next)

Когда выбирать next-intl

Когда выбирать next-i18next

Стоило ли?

Да. 5 часов миграции, а улучшение DX реальное — типобезопасные ключи, чище паттерны в Server Components, никакого кастомного роутинга. Я написал о полной i18n-архитектуре включая роутинг, SEO и RSC-паттерны.


Собираешь мультиязычный Next.js и не уверен, какой i18n-подход выбрать? Напиши — я отгрузил оба и могу сэкономить тебе налог на неправильную библиотеку.