Skip to main content

Išsamus Next.js internacionalizavimo vadovas

Sukonfigūruokite next-intl su App Router, nustatykite lokalių maršrutus ir automatizuokite vertimus naudodami DI.

1

Įdiegti next-intl

next-intl yra vienas paketas, kuris tvarko Next.js App Router lokalių maršrutus, pranešimų įkėlimą ir vertimo kablius.

Terminal
npm install next-intl
Kodėl next-intl, o ne next-i18next? next-intl sukurtas App Router ir serverio komponentams. next-i18next buvo sukurtas Pages Router ir tik ribotai palaiko App Router.
2

Sukurti i18n užklausos konfigūraciją

Sukurkite du failus: src/i18n/request.ts pranešimams įkelti ir src/i18n/routing.ts lokalėms apibrėžti. Jie nustato, kaip next-intl išsprendžia pranešimus ir maršrutus.

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 (numatytasis Next.js 15 paketų kūrimo įrankis) faile next.config.js reikia experimental.turbo.resolveAlias. Be jo gausite klaidų „Couldn't find next-intl config file“.
3

Sukonfigūruoti tarpinę programinę įrangą

Pridėkite middleware.ts lokalėms aptikti, URL perrašyti ir peradresuoti. Tarpinė programinė įranga perima kiekvieną užklausą ir užtikrina, kad būtų pritaikyta tinkama lokalė.

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 PRIVALO būti projekto šakniniame kataloge, o ne src/ viduje. Tai dažniausia next-intl konfigūracijos klaida.
4

Sukurti [locale] aplankų struktūrą

Perkelkite programos maršrutus į app/[locale]/. Pridėkite generateStaticParams, kad komponavimo metu sugeneruotumėte kiekvienos lokalės puslapius. Taip sukuriama URL struktūra /en/about, /de/about ir t. t.

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

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
Kiekviename vertimus naudojančiame page.tsx ir layout.tsx PRIVALOTE iškviesti setRequestLocale(locale). Be jo Next.js grįžta prie dinaminio atvaizdavimo, o komponavimo našumas labai suprastėja.
5

Atnaujinti šakninį maketą

Įkelkite pranešimus naudodami getMessages() ir perduokite juos NextIntlClientProvider šakniniame lokalės makete. html atributą lang nustatykite pagal lokalės parametrą.

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 reikia aiškiai nurodytos ypatybės locale. Jos neįtraukus klientų komponentuose atsiranda sunkiai derinamų subtilių klaidų.
6

Naudoti vertimus komponentuose

Serverio komponentai naudoja getTranslations (asinchroniškai, su await), o kliento komponentai – useTranslations (kablį). Rinkitės pagal tai, kur komponentas atvaizduojamas: serverio komponentai visai neįtraukia vertimų į JavaScript paketą.

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')} />;
}
Išverstam turiniui rinkitės serverio komponentus. Jie neįtraukia vertimo eilučių į kliento JavaScript paketą ir sutrumpina naudotojų įkėlimo laiką.
7

Pridėti SEO: metaduomenis ir hreflang

Naudokite generateMetadata konkrečios lokalės puslapių pavadinimams ir aprašams kurti. Pridėkite alternates.languages hreflang žymoms, kad paieškos sistemos rastų kiekvieno puslapio versijas visomis kalbomis.

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}`])
      ),
    },
  };
}
Jei metadataBase nenustatytas, Vercel komponavimo procesai gali sugeneruoti localhost kaip kanoninį URL. Šakniniame makete visada nustatykite metadataBase į gamybinį domeną.
8

Apdoroti klaidų ir nerastų puslapių rodinius

error.tsx ir not-found.tsx reikia specialiai apdoroti, nes jie gali būti atvaizduojami už įprasto lokalės maketo ribų. Šakniniam not-found.tsx reikia atskiros i18n teikėjo sąrankos lokalizuotiems klaidų pranešimams rodyti.

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 atvaizduoja lokalizuotą 404 puslapį tik tada, kai kode aiškiai iškviečiamas notFound(). Nežinomi maršrutai be atitinkančio puslapio rodo numatytąjį Next.js 404, o ne lokalizuotą versiją.
9

Automatizuoti vertimus

Baigę i18n sąranką išverskite pranešimų failus naudodami DI tiesiai iš IDE arba automatizuokite kiekvieno diegimo vertimą naudodami i18n Agent CLI CI/CD konvejeryje.

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)
Išmanioms atsarginėms lokalėms naudokite next-intl-localechain: kai nėra Brazilijos portugalų kalbos, pt-BR naudotojas matys pt-PT vertimus, o ne grįš prie anglų kalbos.

Automatizuoti vertimo kokybę

Naudodami i18n-validate prieš išleidimą aptikite trūkstamus raktus ir sugadintus vietos rezervavimo ženklus. Kol dar nėra tikrų vertimų, patikrinkite UI su netikrais i18n-pseudo vertimais.

Atvirojo kodo įrankiai Next.js i18n

Šie atvirojo kodo paketai sprendžia dažnas Next.js internacionalizavimo darbo eigų problemas.

next-intl-localechain

Kai trūksta vertimo, standartinis next-intl iškart grįžta prie numatytosios lokalės. Brazilijos portugalų kalbos naudotojas vietoje puikių pt-PT vertimų mato anglų kalbą. next-intl-localechain prideda išmanias atsargines grandines: jis giliai sujungia susijusių lokalių vertimus, kad regionų naudotojai visada matytų artimiausią esamą vertimą.

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'
}));
Automatiškai giliai sujungia vertimus lokalių grandinėse
Integruotos grandinės portugalų, ispanų, prancūzų, vokiečių ir kitoms kalboms
Sklandžiai ir be klaidų praleidžia trūkstamus pranešimų failus
Vienos eilutės sąranka – apgaubia esamą getRequestConfig
Peržiūrėti GitHub

@i18n-agent/cli

Komandų eilutės įrankis Next.js pranešimų failams versti neišeinant iš terminalo. Tiesiogiai verskite failus, tikrinkite užduočių būseną ir atsisiųskite rezultatus. Veikia CI/CD konvejeriuose autentifikuojant API raktu ir leidžia visiškai automatizuoti lokalizavimo darbo eigas.

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
Verskite JSON, YAML, PO ir kitus i18n failų formatus iš terminalo
Paruošta CI/CD: automatiniuose konvejeriuose autentifikuokite aplinkos kintamuoju
Stebėkite užduoties būseną, tęskite nepavykusias užduotis ir atsisiųskite rezultatus
Mašininio skaitymo JSON išvestis scenarijams ir automatizavimui
Peržiūrėti GitHub

Dažnos klaidos

„Unable to find next-intl locale“

Tarpinė programinė įranga neatitiko užklausos. Patikrinkite: ar middleware.ts yra projekto šaknyje? Ar matcher šablonas tinkamai neįtraukia statinių failų? Ar lokalė įtraukta į maršrutų konfigūraciją?

Netikėtas dinaminis atvaizdavimas

Puslapyje ar makete trūksta setRequestLocale(locale). Be jo next-intl lokalei aptikti naudoja antraštes ir slapukus, todėl priverstinai įjungiamas dinaminis atvaizdavimas ir neleidžiama generuoti statiškai.

Lygiagretūs maršrutai neveikia su i18n

Lygiagretūs (@modal) ir perimantys ((.)photo) maršrutai yra žinomai nesuderinami su dinaminiu segmentu [locale]. Šiems išplėstiniams maršrutų šablonams apeiti naudokite tarpine programine įranga pagrįstus maršrutus.

Keičiant kalbą prarandamas dabartinis maršrutas

Keisdami lokales išsaugokite dabartinį kelio pavadinimą naudodami usePathname() ir pakeiskite tik lokalės segmentą. Atsargiai elkitės su dinaminiais maršruto parametrais – juos reikia iš naujo išspręsti naujai lokalei.

Rekomenduojama failų struktūra

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

Išbandykite i18n Agent dabar

Nuvilkite vertimo failą čia

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

arba spustelėkite norėdami pasirinkti

Tikslinės kalbos

Registruotis nereikiaMomentinis įvertis

Atsarginė lokalė su next-intl-localechain

Kai regioninėje lokalėje, pavyzdžiui, pt-BR, trūksta vertimo rakto, next-intl iškart pereina prie numatytosios lokalės, užuot pirmiausia patikrinęs pirminę lokalę 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`),
});

Visą palaikomų sistemų sąrašą ir 75 integruotas grandines rasite mūsų atsarginių lokalių vadove. Learn more →

Dažnai užduodami klausimai