Skip to main content

Повний посібник з інтернаціоналізації в Next.js

Налаштуйте next-intl з App Router, сконфігуруйте маршрутизацію за локалями й автоматизуйте переклад за допомогою ШІ.

1

Установити next-intl

next-intl — це єдиний пакет, який забезпечує маршрутизацію за локалями, завантаження повідомлень і хуки перекладу для Next.js App Router.

Terminal
npm install next-intl
Чому варто вибрати next-intl замість next-i18next? next-intl створено для App Router і серверних компонентів. next-i18next було розроблено для Pages Router, тому його підтримка App Router обмежена.
2

Створити конфігурацію запитів i18n

Створіть два файли: src/i18n/request.ts для завантаження повідомлень і src/i18n/routing.ts для визначення локалей. Вони визначають, як next-intl завантажує повідомлення та формує маршрути.

src/i18n/routing.ts
// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
import { createNavigation } from 'next-intl/navigation';

export const routing = defineRouting({
  locales: ['en', 'de', 'ja', 'es'],
  defaultLocale: 'en',
  localePrefix: 'as-needed',  // /about for en, /de/about for de
});

export const { Link, redirect, usePathname, useRouter } =
  createNavigation(routing);
Turbopack (стандартний збирач у Next.js 15) потребує experimental.turbo.resolveAlias у Вашому next.config.js. Без цього виникають помилки "Couldn't find next-intl config file".
3

Налаштувати проміжне програмне забезпечення

Додайте middleware.ts для визначення локалі, перезаписування URL і перенаправлень. Проміжне програмне забезпечення перехоплює кожен запит і забезпечує застосування правильної локалі.

middleware.ts
// middleware.ts  <- Must be in project ROOT, not src/
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';

export default createMiddleware(routing);

export const config = {
  matcher: ['/((?!api|_next|.*\\..*).*)'],
};
middleware.ts ОБОВ’ЯЗКОВО має бути в кореневій папці Вашого проєкту, а не всередині src/. Це найпоширеніша помилка налаштування next-intl.
4

Налаштувати структуру папки [locale]

Перемістіть маршрути застосунку до app/[locale]/. Додайте generateStaticParams, щоб під час збирання створювати сторінки для кожної локалі. Так формується структура URL /en/about, /de/about тощо.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
Ви ОБОВ’ЯЗКОВО маєте викликати setRequestLocale(locale) у кожному page.tsx і layout.tsx, де використовуються переклади. Без цього Next.js переходить до динамічного рендерингу, а продуктивність збирання істотно погіршується.
5

Оновити кореневий макет

Завантажте повідомлення за допомогою getMessages() і передайте їх до NextIntlClientProvider у кореневому макеті локалі. Установіть для атрибута lang елемента html значення параметра локалі.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, setRequestLocale } from 'next-intl/server';
import { routing } from '@/i18n/routing';
import { notFound } from 'next/navigation';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

export default async function LocaleLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  const { locale } = await params;
  if (!routing.locales.includes(locale as any)) notFound();

  setRequestLocale(locale);
  const messages = await getMessages();

  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider locale={locale} messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}
NextIntlClientProvider потребує явно вказаної властивості locale. Якщо її пропустити, у клієнтських компонентах виникатимуть приховані помилки, які складно діагностувати.
6

Використати переклади в компонентах

Серверні компоненти використовують getTranslations (async, await), а клієнтські — useTranslations (хук). Вибирайте відповідно до місця рендерингу компонента: завдяки серверним компонентам переклади взагалі не потрапляють до пакета JavaScript.

app/[locale]/page.tsx
// Server Component (default)
import { getTranslations, setRequestLocale } from 'next-intl/server';

export default async function AboutPage({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  setRequestLocale(locale);
  const t = await getTranslations('AboutPage');

  return <h1>{t('title')}</h1>;
}

// Client Component ('use client')
'use client';
import { useTranslations } from 'next-intl';

export default function SearchBar() {
  const t = useTranslations('SearchBar');
  return <input placeholder={t('placeholder')} />;
}
Віддавайте перевагу серверним компонентам для перекладеного вмісту. Так рядки перекладу не потрапляють до клієнтського пакета JavaScript, що скорочує час завантаження для користувачів.
7

Додати SEO: метадані та hreflang

Використовуйте generateMetadata, щоб створювати заголовки й описи сторінок для кожної локалі. Додайте alternates.languages для тегів hreflang, щоб пошукові системи знаходили всі мовні версії кожної сторінки.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx or any page.tsx
import { getTranslations } from 'next-intl/server';
import { routing } from '@/i18n/routing';

export async function generateMetadata({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: 'Metadata' });

  return {
    title: t('title'),
    description: t('description'),
    alternates: {
      languages: Object.fromEntries(
        routing.locales.map((l) => [l, `/${l}`])
      ),
    },
  };
}
На Vercel під час збирання localhost може стати канонічною URL-адресою, якщо не встановлено metadataBase. Завжди задавайте для metadataBase у кореневому макеті домен виробничого середовища.
8

Опрацювати сторінки помилок і сторінки «Не знайдено»

error.tsx і not-found.tsx потребують особливого опрацювання, оскільки можуть відображатися поза звичайним макетом локалі. Для показу локалізованих повідомлень про помилки кореневий not-found.tsx потребує власного налаштування постачальника i18n.

app/[locale]/error.tsx
// app/[locale]/error.tsx
'use client';
import { useTranslations } from 'next-intl';

export default function Error() {
  const t = useTranslations('Error');
  return (
    <div>
      <h1>{t('title')}</h1>
      <p>{t('description')}</p>
    </div>
  );
}

// app/not-found.tsx (root level -- needs own provider)
import { routing } from '@/i18n/routing';

export default async function GlobalNotFound() {
  return (
    <html lang={routing.defaultLocale}>
      <body>
        <h1>404 - Page Not Found</h1>
      </body>
    </html>
  );
}
Next.js відображає Вашу локалізовану сторінку 404, лише коли у Вашому коді явно викликається notFound(). Для невідомих маршрутів без відповідної сторінки відображається стандартна сторінка 404 Next.js, а не Ваша локалізована версія.
9

Автоматизувати переклад

Після завершення налаштування i18n перекладайте файли повідомлень за допомогою ШІ безпосередньо в IDE або використовуйте CLI i18n Agent у конвеєрі CI/CD для автоматичного перекладу під час кожного розгортання.

Terminal
# In your IDE, ask your AI assistant:
> Translate messages/en.json to German, Japanese, and Spanish

✓ messages/de.json created (1.1s)
✓ messages/ja.json created (1.4s)
✓ messages/es.json created (1.0s)
Використовуйте next-intl-localechain для інтелектуальних резервних локалей: якщо бразильська португальська недоступна, користувач із локаллю pt-BR побачить переклад pt-PT замість переходу до англійської.

Автоматизувати контроль якості перекладу

Виявляйте відсутні ключі та пошкоджені заповнювачі до випуску за допомогою i18n-validate. Перевіряйте інтерфейс із псевдоперекладами через i18n-pseudo, перш ніж будуть готові справжні переклади.

Інструменти з відкритим кодом для i18n у Next.js

Ці пакети з відкритим кодом усувають типові труднощі в процесах інтернаціоналізації Next.js.

next-intl-localechain

Стандартний next-intl одразу переходить до Вашої стандартної локалі, якщо переклад відсутній. Через це користувач із бразильською португальською бачить англійський текст замість цілком придатного перекладу pt-PT. next-intl-localechain додає інтелектуальні ланцюжки резервних локалей: він глибоко об’єднує переклади зі споріднених локалей, тому користувачі регіональних варіантів завжди бачать найближчий доступний переклад.

src/i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { withLocaleChain } from 'next-intl-localechain';

export default getRequestConfig(withLocaleChain({
  loadMessages: (locale) =>
    import(`../../messages/${locale}.json`).then(m => m.default),
  defaultLocale: 'en'
}));
Автоматично глибоко об’єднує переклади в ланцюжках локалей
Містить готові ланцюжки для португальської, іспанської, французької, німецької та інших мов
Коректно пропускає відсутні файли повідомлень без помилок
Налаштування одним рядком — обгортає Ваш наявний getRequestConfig
Переглянути на GitHub

@i18n-agent/cli

Інструмент командного рядка для перекладу файлів повідомлень Next.js без виходу з термінала. Перекладайте файли безпосередньо, перевіряйте стан завдань і завантажуйте результати. Працює в конвеєрах CI/CD з автентифікацією за ключем API та забезпечує повністю автоматизовані процеси локалізації.

Terminal
# Install the CLI
npm install -g @i18n-agent/cli

# Authenticate
i18nagent login

# Translate your message files
i18nagent translate ./messages/en.json --lang de,ja,es

# Or use in CI/CD with an API key
export I18N_AGENT_API_KEY=your-key-here
i18nagent translate ./messages/en.json --lang de,ja,es
Перекладає JSON, YAML, PO та інші формати файлів i18n із термінала
Готовий до CI/CD — автентифікується через змінну середовища в автоматизованих конвеєрах
Відстежує стан завдань, поновлює виконання завдань після збою й завантажує результати
Надає придатні для машинного опрацювання результати у форматі JSON для сценаріїв та автоматизації
Переглянути на GitHub

Поширені помилки

"Unable to find next-intl locale"

Проміжне програмне забезпечення не охопило запит. Перевірте: чи розташовано middleware.ts у кореневій папці проєкту? Чи правильно шаблон matcher виключає статичні файли? Чи додано локаль до конфігурації маршрутизації?

Неочікуваний динамічний рендеринг

На сторінці або в макеті немає setRequestLocale(locale). Без нього next-intl визначає локаль за заголовками або файлами cookie, що примусово вмикає динамічний рендеринг і унеможливлює статичне генерування.

Паралельні маршрути не працюють з i18n

Паралельні маршрути (@modal) і маршрути перехоплення ((.)photo) мають відомі несумісності з динамічним сегментом [locale]. Для таких розширених схем маршрутизації використовуйте як обхідне рішення маршрутизацію на основі проміжного програмного забезпечення.

Під час перемикання мови втрачається поточний маршрут

Під час перемикання локалі збережіть поточний pathname за допомогою usePathname() і замініть лише сегмент локалі. Будьте уважні з параметрами динамічних маршрутів: їх потрібно повторно визначити для нової локалі.

Рекомендована структура файлів

Project Structure
my-nextjs-app/
├── middleware.ts              # Locale routing (project root!)
├── next.config.mjs
├── messages/
│   ├── en.json                # Source messages
│   ├── de.json
│   └── ja.json
├── src/
│   ├── i18n/
│   │   ├── request.ts         # Message loading config
│   │   └── routing.ts         # Locale definitions
│   └── app/
│       └── [locale]/
│           ├── layout.tsx     # Root locale layout
│           ├── page.tsx       # Home page
│           ├── error.tsx      # Localized error page
│           ├── not-found.tsx  # Localized 404
│           └── about/
│               └── page.tsx
└── package.json

Спробуйте i18n Agent зараз

Перетягніть сюди файл для перекладу

JSON, YAML, PO, XML, CSV, Markdown, Properties

або натисніть, щоб вибрати

Цільові мови

Реєстрація не потрібнаМиттєвий розрахунок

Резервні локалі з next-intl-localechain

Якщо в регіональній локалі на зразок pt-BR немає ключа перекладу, next-intl одразу переходить до стандартної локалі, не перевіряючи спочатку батьківську локаль pt.

Terminal
npm install next-intl-localechain
Configuration
import { withLocaleChain } from 'next-intl-localechain';

export default withLocaleChain({
  fallbacks: {
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
  },
  defaultLocale: 'en',
  loadMessages: (locale) => import(`./messages/${locale}.json`),
});

Перегляньте наш посібник із резервних локалей, щоб дізнатися про всі підтримувані фреймворки та 75 готових ланцюжків. Learn more →

Поширені запитання