
De complete handleiding voor internationalisering in Next.js
Configureer next-intl met de App Router, stel locale-routering in en automatiseer vertalingen met AI.
next-intl installeren
next-intl is één pakket dat locale-routering, het laden van berichten en vertaalhooks voor de Next.js App Router afhandelt.
npm install next-intlDe i18n-aanvraagconfiguratie maken
Maak twee bestanden: src/i18n/request.ts voor het laden van berichten en src/i18n/routing.ts voor locale-definities. Hiermee stel je in hoe next-intl berichten en routes bepaalt.
// 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 configureren
Voeg middleware.ts toe om localedetectie, het herschrijven van URL's en omleidingen af te handelen. De middleware onderschept elke aanvraag en zorgt dat de juiste locale wordt toegepast.
// 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|.*\\..*).*)'],
};De mapstructuur [locale] instellen
Verplaats je app-routes naar app/[locale]/. Voeg generateStaticParams toe om tijdens het bouwen pagina's voor elke locale te genereren. Zo ontstaat de URL-structuur /en/about, /de/about enz.
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
}Je hoofdlay-out bijwerken
Laad berichten met getMessages() en geef ze in de hoofdlay-out voor locales door aan NextIntlClientProvider. Stel het html-attribuut lang in op basis van de locale-parameter.
// 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>
);
}Vertalingen in componenten gebruiken
Servercomponenten gebruiken getTranslations (async, await). Clientcomponenten gebruiken useTranslations (hook). Kies op basis van waar je component wordt gerenderd — met servercomponenten blijven vertalingen volledig buiten de JavaScript-bundel.
// 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 toevoegen: metadata en hreflang
Gebruik generateMetadata om paginaspecifieke titels en beschrijvingen per locale te maken. Voeg alternates.languages toe voor hreflang-tags, zodat zoekmachines alle taalversies van elke pagina vinden.
// 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}`])
),
},
};
}Fout- en niet-gevondenpagina's afhandelen
error.tsx en not-found.tsx vereisen speciale verwerking, omdat ze buiten de normale locale-lay-out kunnen worden gerenderd. Het bestand not-found.tsx in de hoofdmap heeft een eigen configuratie van de i18n-provider nodig om gelokaliseerde foutmeldingen te tonen.
// 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>
);
}Vertalingen automatiseren
Zodra je i18n-configuratie klaar is, vertaal je berichtbestanden rechtstreeks vanuit je IDE met AI of gebruik je de i18n Agent CLI in je CI/CD-pipeline om bij elke implementatie automatisch te vertalen.
# 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)De vertaalkwaliteit automatisch bewaken
Opensourcetools voor i18n in Next.js
Deze opensourcepakketten lossen veelvoorkomende knelpunten in internationaliseringsworkflows voor Next.js op.
next-intl-localechain
Standaard valt next-intl bij een ontbrekende vertaling rechtstreeks terug op je standaardlocale. Een gebruiker die Braziliaans-Portugees gebruikt, ziet daardoor Engels in plaats van prima vertalingen voor pt-PT. next-intl-localechain voegt intelligente fallbackketens toe en voegt vertalingen uit verwante locales recursief samen, zodat regionale gebruikers altijd de best passende beschikbare vertaling zien.
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
Een opdrachtregeltool waarmee je berichtbestanden voor Next.js vertaalt zonder de terminal te verlaten. Vertaal bestanden rechtstreeks, controleer de taakstatus en download resultaten. Werkt in CI/CD-pipelines met authenticatie via een API-sleutel voor volledig geautomatiseerde lokalisatieworkflows.
# 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,esVeelvoorkomende valkuilen
"Unable to find next-intl locale"
De middleware kwam niet overeen met de aanvraag. Controleer het volgende: staat middleware.ts in de hoofdmap van het project? Sluit het matcherpatroon statische bestanden correct uit? Is de locale opgenomen in je routeringsconfiguratie?
Onverwachte dynamische rendering
setRequestLocale(locale) ontbreekt op een pagina of in een lay-out. Zonder deze aanroep gebruikt next-intl headers of cookies om de locale te detecteren. Dit dwingt dynamische rendering af en verhindert statische generatie.
Parallelle routes werken niet met i18n
Parallelle routes (@modal) en onderscheppende routes ((.)photo) zijn niet volledig compatibel met het dynamische segment [locale]. Gebruik routering via middleware als tijdelijke oplossing voor deze geavanceerde routeringspatronen.
Bij het wisselen van taal gaat de huidige route verloren
Behoud bij het wisselen van locale het huidige pad met usePathname() en vervang alleen het locale-segment. Let op met dynamische routeparameters: die moeten voor de nieuwe locale opnieuw worden bepaald.
Aanbevolen bestandsstructuur
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.jsonProbeer i18n Agent nu
Zet je vertaalbestand hier neer
JSON, YAML, PO, XML, CSV, Markdown, Properties
of klik om een bestand te selecteren
Doeltalen
Locale-fallback met next-intl-localechain
Als een vertaalsleutel ontbreekt in een regionale locale zoals pt-BR, springt next-intl meteen naar de standaardlocale zonder eerst de bovenliggende locale pt te controleren.
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`),
});Bekijk onze handleiding voor locale-fallbacks voor de volledige lijst met ondersteunde frameworks en 75 ingebouwde ketens. Learn more →