Skip to main content

Den komplette guiden til internasjonalisering i Next.js

Sett opp next-intl med App Router, konfigurer lokalitetsruting, og automatiser oversettelser med AI.

1

Installer next-intl

next-intl er en enkelt pakke som håndterer lokalitetsruting, innlasting av meldinger og oversettelses-hooks for Next.js App Router.

Terminal
npm install next-intl
Hvorfor next-intl fremfor next-i18next? next-intl er bygget for App Router og serverkomponenter. next-i18next var designet for Pages Router og har begrenset støtte for App Router.
2

Opprett i18n-forespørselskonfigurasjonen

Opprett to filer: src/i18n/request.ts for innlasting av meldinger og src/i18n/routing.ts for lokalitetsdefinisjoner. Disse konfigurerer hvordan next-intl løser opp meldinger og ruter.

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 (standard bundler i Next.js 15) krever experimental.turbo.resolveAlias i next.config.js. Uten det får du feilmeldingen «Couldn't find next-intl config file».
3

Konfigurer middleware

Legg til middleware.ts for å håndtere lokalitetsgjenkjenning, URL-omskriving og omdirigeringer. Middlewaren fanger opp hver forespørsel og sørger for at riktig lokalitet blir brukt.

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 MÅ ligge i prosjektets rotmappe, ikke inni src/. Dette er den desidert vanligste konfigurasjonsfeilen med next-intl.
4

Sett opp mappestrukturen for [locale]

Flytt apprutene dine inn i app/[locale]/. Legg til generateStaticParams for å generere sider for hver lokalitet ved byggetidspunktet. Dette skaper URL-strukturen /en/about, /de/about osv.

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

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
Du MÅ kalle setRequestLocale(locale) i hver page.tsx og layout.tsx som bruker oversettelser. Uten det faller Next.js tilbake til dynamisk gjengivelse, og byggeytelsen din forringes betydelig.
5

Oppdater rot-layouten din

Last inn meldinger med getMessages() og send dem til NextIntlClientProvider i rot-lokalitetslayouten din. Sett html-attributtet lang fra lokalitetsparameteren.

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 krever en eksplisitt locale-prop. Å utelate den forårsaker subtile feil i klientkomponenter som er vanskelige å feilsøke.
6

Bruk oversettelser i komponenter

Serverkomponenter bruker getTranslations (async, await). Klientkomponenter bruker useTranslations (hook). Velg basert på hvor komponenten din rendres. Serverkomponenter holder oversettelser helt utenfor JavaScript-bunten.

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')} />;
}
Foretrekk serverkomponenter for oversatt innhold. De holder oversettelsesstrenger utenfor klientens JavaScript-bunt, noe som reduserer innlastingstiden for brukerne.
7

Legg til SEO: metadata og hreflang

Bruk generateMetadata til å produsere lokalitetsspesifikke sidetitler og beskrivelser. Legg til alternates.languages for hreflang-tagger, slik at søkemotorer oppdager alle språkversjoner av hver side.

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}`])
      ),
    },
  };
}
På Vercel kan bygg generere localhost som den kanoniske URL-en hvis metadataBase ikke er satt. Sett alltid metadataBase i rotlayouten til produksjonsdomenet ditt.
8

Håndter feilsider og sider som ikke finnes

error.tsx og not-found.tsx trenger spesiell håndtering fordi de kan rendres utenfor den vanlige lokalitetslayouten. Rotens not-found.tsx krever sitt eget i18n-provideroppsett for å vise lokaliserte feilmeldinger.

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 rendrer bare den lokaliserte 404-siden din når notFound() kalles eksplisitt i koden din. Ukjente ruter uten en tilhørende side viser standard 404-siden til Next.js, ikke din lokaliserte versjon.
9

Automatiser oversettelser

Når i18n-oppsettet ditt er fullført, kan du oversette meldingsfilene dine med AI direkte fra IDE-en, eller bruke i18n Agent CLI i CI/CD-pipelinen din for automatisert oversettelse ved hver driftsetting.

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)
Bruk next-intl-localechain for intelligente reservekjeder for lokaliteter. En pt-BR-bruker får pt-PT-oversettelser i stedet for engelsk når brasiliansk portugisisk ikke er tilgjengelig.

Automatiser oversettelseskvalitet

Fang opp manglende nøkler og ødelagte plassholdere før de driftsettes, med i18n-validate. Test grensesnittet ditt med pseudooversettelser ved hjelp av i18n-pseudo før de ekte oversettelsene kommer.

Verktøy med åpen kildekode for Next.js i18n

Disse pakkene med åpen kildekode løser vanlige smertepunkter i arbeidsflyter for internasjonalisering i Next.js.

next-intl-localechain

Standard next-intl går direkte tilbake til standardlokaliteten din når en oversettelse mangler. En brasiliansk-portugisisk bruker får engelsk i stedet for fullt brukbare pt-PT-oversettelser. next-intl-localechain legger til intelligente reservekjeder. Verktøyet slår sammen oversettelser fra beslektede lokaliteter rekursivt, slik at regionale brukere alltid får den nærmeste tilgjengelige oversettelsen.

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'
}));
Slår automatisk sammen oversettelser rekursivt på tvers av lokalitetskjeder
Innebygde kjeder for portugisisk, spansk, fransk, tysk og flere
Hopper elegant over manglende meldingsfiler uten feil
Oppsett på én linje. Pakker inn den eksisterende getRequestConfig-en din
Se på GitHub

@i18n-agent/cli

Et kommandolinjeverktøy for å oversette Next.js-meldingsfilene dine uten å forlate terminalen. Oversett filer direkte, sjekk jobbstatus og last ned resultater. Fungerer i CI/CD-pipeliner med API-nøkkelautentisering for helautomatiserte lokaliseringsarbeidsflyter.

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
Oversett JSON, YAML, PO og andre i18n-filformater fra terminalen
Klar for CI/CD. Autentiser via miljøvariabel for automatiserte pipeliner
Spor jobbstatus, gjenoppta mislykkede jobber og last ned resultater
Maskinlesbar JSON-utdata for skripting og automatisering
Se på GitHub

Vanlige fallgruver

«Unable to find next-intl locale»

Middlewaren matchet ikke forespørselen. Sjekk: Ligger middleware.ts i prosjektets rotmappe? Ekskluderer matcher-mønsteret statiske filer riktig? Er lokaliteten inkludert i rutingkonfigurasjonen din?

Uventet dynamisk rendering

setRequestLocale(locale) mangler fra en side eller layout. Uten det bruker next-intl headere/informasjonskapsler for å oppdage lokaliteten, noe som tvinger frem dynamisk rendering og forhindrer statisk generering.

Parallelle ruter fungerer ikke med i18n

Parallelle ruter (@modal) og avskjærende ruter ((.)photo) har kjente inkompatibiliteter med det dynamiske [locale]-segmentet. Bruk middleware-basert ruting som en løsning for disse avanserte rutingmønstrene.

Språkbytte mister gjeldende rute

Når du bytter lokalitet, bevar gjeldende pathname ved hjelp av usePathname() og erstatt bare lokalitetssegmentet. Vær forsiktig med dynamiske ruteparametere. De må løses opp på nytt for den nye lokaliteten.

Anbefalt filstruktur

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

Prøv i18n Agent nå

Slipp oversettelsesfilen din her

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

eller klikk for å bla gjennom

Målspråk

Ingen registrering krevesUmiddelbart estimat

Lokalitetsreserveløsning med next-intl-localechain

Når en oversettelsesnøkkel mangler i en regional lokalitet som pt-BR, hopper next-intl rett til standardlokaliteten i stedet for først å sjekke foreldrelokaliteten 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`),
});

Se vår guide til lokalitetsreserveløsning for den fullstendige listen over støttede rammeverk og 75 innebygde kjeder. Learn more →

Ofte stilte spørsmål