
Пълно ръководство за интернационализация на Next.js
Настройте next-intl с App Router, конфигурирайте маршрутизирането по локал и автоматизирайте преводите с ИИ.
Инсталирайте next-intl
next-intl е единен пакет, който управлява маршрутизирането по локал, зареждането на съобщения и hooks за превод в Next.js App Router.
npm install next-intlСъздайте конфигурацията на i18n за заявките
Създайте два файла: src/i18n/request.ts за зареждане на съобщения и src/i18n/routing.ts за дефиниране на локалите. Те определят как next-intl намира съобщенията и маршрутите.
// 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);Конфигурирайте middleware
Добавете middleware.ts за откриване на локала, пренаписване на URL адреси и пренасочвания. middleware прихваща всяка заявка и гарантира прилагането на правилния локал.
// 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|.*\\..*).*)'],
};Настройте структурата на папката [locale]
Преместете маршрутите на приложението в app/[locale]/. Добавете generateStaticParams, за да генерирате страниците за всеки локал по време на компилацията. Така се създава URL структурата /en/about, /de/about и т.н.
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}Актуализирайте основното оформление
Заредете съобщенията с getMessages() и ги подайте към NextIntlClientProvider в основното оформление за локала. Задайте атрибута lang на html от параметъра за локал.
// 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>
);
}Използвайте преводите в компоненти
Сървърните компоненти използват getTranslations (async, await). Клиентските компоненти използват useTranslations (hook). Изберете според мястото на визуализиране на компонента — сървърните компоненти изцяло изключват преводите от JavaScript пакета.
// 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')} />;
}Добавете SEO: метаданни и hreflang
Използвайте generateMetadata, за да създавате заглавия и описания на страниците за всеки локал. Добавете alternates.languages за тагове hreflang, за да могат търсачките да откриват всички езикови версии на всяка страница.
// 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}`])
),
},
};
}Обработвайте страниците за грешки и ненамерено съдържание
error.tsx и not-found.tsx изискват специална обработка, защото могат да се визуализират извън обичайното оформление за локала. Основният not-found.tsx изисква собствена конфигурация на i18n доставчик, за да показва локализирани съобщения за грешки.
// 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>
);
}Автоматизирайте преводите
След като завършите настройката на i18n, превеждайте файловете със съобщения чрез ИИ направо от Вашата IDE или използвайте i18n Agent CLI във Вашия CI/CD пайплайн за автоматизиран превод при всяко внедряване.
# 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)Автоматизирайте контрола на качеството на превода
Инструменти с отворен код за i18n в Next.js
Тези пакети с отворен код решават често срещани затруднения в процесите за интернационализация на Next.js.
next-intl-localechain
Стандартният next-intl преминава направо към Вашия локал по подразбиране, когато липсва превод. Потребител с бразилски португалски вижда английски вместо напълно подходящите преводи за pt-PT. next-intl-localechain добавя интелигентни резервни вериги — той рекурсивно обединява преводите от сродни локали, така че потребителите на регионални варианти винаги да виждат най-близкия наличен превод.
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'
}));@i18n-agent/cli
Инструмент за команден ред, с който превеждате файловете със съобщения на Next.js, без да напускате терминала. Превеждайте файлове директно, проверявайте състоянието на задачите и изтегляйте резултатите. Работи в CI/CD пайплайни с удостоверяване чрез API ключ за напълно автоматизирани процеси на локализация.
# 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Често срещани затруднения
"Unable to find next-intl locale"
Заявката не е съвпаднала с правилата на middleware. Проверете: намира ли се middleware.ts в основната директория на проекта? Изключва ли правилно шаблонът matcher статичните файлове? Включен ли е локалът в конфигурацията за маршрутизиране?
Неочаквано динамично визуализиране
setRequestLocale(locale) липсва от страница или оформление. Без нея next-intl използва заглавки/бисквитки, за да открие локала, което налага динамично визуализиране и възпрепятства статичното генериране.
Паралелните маршрути не работят с i18n
Паралелните маршрути (@modal) и прихващащите маршрути ((.)photo) имат известни несъвместимости с динамичния сегмент [locale]. Като временно решение за тези усъвършенствани модели на маршрутизиране използвайте маршрутизиране чрез middleware.
При смяна на езика текущият маршрут се губи
Когато сменяте локала, запазете текущия pathname чрез usePathname() и заменете само сегмента за локала. Внимавайте с параметрите на динамичните маршрути — те трябва да бъдат определени наново за новия локал.
Препоръчителна файлова структура
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.
npm install next-intl-localechainimport { 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 →