

Next.js har to offisielle i18n-dokumentasjonssider som beskriver helt forskjellige systemer, uten kryssreferanser mellom dem.
Den ene dekker Pages Router . Den andre dekker App Router . Ingen av dem forklarer hvordan de to forholder seg, hvilke biblioteker som skal brukes, eller hvordan man håndterer hreflang for flerspråklig SEO.
Vi skal bygge bro mellom begge ruterne. Vi skal gå gjennom rutingsstrategier, valg av bibliotek, oppsett av mellomprogramvare, oversettelser av serverkomponenter og flerspråklig SEO.
Målet vårt er å lage en nyttig ressurs for utviklere som har blitt bedt om å legge til språkstøtte i en Next.js-app og trenger et klart bilde før de bestemmer seg for en strategi. La oss komme i gang!
Internasjonalisering har tre lag:
Next.js hjelper bare med ruting.
Pages Router har hatt innebygd i18n-ruting siden v10.0.0. En konfigurasjonsblokk med tre felt i next.config.js håndterer lokalitetsdeteksjon, URL-prefiksering og omdirigeringer automatisk.
App-ruteren er annerledes. Dokumentasjonssiden for i18n dokumenterer et mønster du setter sammen selv ved hjelp av mellomvare, en [lokal] dynamisk segment og et bibliotek.
Når det gjelder oversettelser og formatering, er du overlatt til deg selv, uavhengig av hvilken ruter du bruker. App Router-dokumentasjonen viser alle kompatible biblioteker, men gir ingen veiledning om hvilket du skal velge. Ingen av dokumentasjonssidene dekker hreflang-tagger eller flerspråklige nettstedskart.
Pages Router-tilnærmingen er en konfigurasjonsendring. Legg til en i18n-blokk i next.config.js med tre felt:
// next.config.js
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
}Det er det.
Next.js oppdager automatisk språkinnstillinger fra Godta språk overskrift, respekterer en NESTE_LOKALE overstyring av informasjonskapsler, og eksponerer den aktive språkinnstillingen via brukRouter().lokalDu trenger ikke mellomvare eller omstrukturering av kataloger.
App-ruteren har ingen tilsvarende konfigurasjon. Du bygger rutingen selv fra tre deler:
@formatjs/intl-localematcher og forhandler å analysere Godta språk overskrifter. De offisielle dokumentene lar den faktiske deteksjonslogikken stå som en ellipse: funksjon getLocale(forespørsel) { ... }Vi fyller ut det i neste avsnitt.[lokal] dynamisk segment omslutter hele app/ katalog. Hver rute blir språktilpasset gjennom mappestrukturen.genererStatiskeParamer forhåndsgjengir hver språkvariant under bygging.Av de tre delene er generateStaticParams den som erstatter det Pages Router håndterte automatisk under byggetid.
export function generateStaticParams() {
return [{ locale: 'en' }, { locale: 'fr' }, { locale: 'de' }]
}🚨 Pages Routers innebygde i18n fungerer ikke med utdata: 'eksport'Hvis du trenger en fullstendig statisk eksport, trenger du manuell mappebasert ruting i stedet. Denne begrensningen gjelder kun for den innebygde konfigurasjonen. Begge ruterne støtter statisk eksport med manuelt oppsett.
Før du velger et bibliotek, velg en rutingsstrategi. Det påvirker SEO, DNS-oppsett og hvor mye mellomvare du skal skrive:
neste-intl støtter det som et førsteklasses alternativ.For offentlige nettsteder der SEO er viktig, er underveisruting riktig standard. Domeneruting er verdt kompleksiteten bare hvis sterke geografiske målrettingssignaler er et spesifikt krav.
Hvis du heller ikke vil administrere URL-strukturen manuelt, håndterer Weglot omvendte proxy ruting av underkataloger og underdomener automatisk, inkludert hreflang-injeksjon og oversatte URL-er.
Som vi nevnte tidligere, lister de offisielle dokumentene opp biblioteker uten å anbefale noen. Slik sammenligner du hovedalternativene:
next-intl er de facto-standarden for App Router. RSC-støtte er innebygd, ruting er integrert, og TypeScript-autofullføring fungerer uten ekstra konfigurasjon.
react-i18next passer bedre hvis du er på Pages Router eller allerede bruker i18next andre steder i stacken din. Støtte for App Router fungerer, men krever mer manuell oppsett.
Lingui passer for team med eksisterende .po -filkanaler. Oversettelser hentes ut under bygging, slik at ubrukte meldinger aldri sendes.
💡 Paraglide JS er ikke akkurat blant de store aktørene, men det er verdt å merke seg som et kompilatorbasert alternativ med mindre buntutdata. Hvis du er interessert, må du imidlertid være oppmerksom på at økosystemet deres er yngre enn de andre.
For dato- og tallformatering pakker next-intl de innebygde Intl API-ene via useFormatter. De andre delegerer til FormatJS , eller lar det være opp til deg å kalle Intl.DateTimeFormat og Intl.NumberFormat direkte.
💡 Disse bibliotekene håndterer gjengivelse. Noen må fortsatt produsere oversettelsene og holde dem synkroniserte etter hvert som innholdet endres. Weglot opererer på et helt annet lag, og administrerer oversettelsesinnhold via omvendt proxy utenfor kodebasen. Ikke tenk på det som en erstatning for et bibliotek.
Next.js 16 omdøpte middleware.ts til proxy.ts . Dette ble gjort fordi «middleware» var misvisende og antydet generisk logikk i appen. I virkeligheten kjører filen ved nettverksgrensen, og fanger opp og endrer forespørsler som en proxy før de når applikasjonen.
Her er en komplett implementering av lokalitetsdeteksjon og omdirigering som fyller den nevnte ellipsen i den offisielle dokumentasjonen:
// proxy.ts
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import { NextRequest, NextResponse } from 'next/server'
const locales = ['en', 'fr', 'de']
const defaultLocale = 'en'
function getLocale(request: NextRequest): string {
const cookie = request.cookies.get('NEXT_LOCALE')?.value
if (cookie && locales.includes(cookie)) return cookie
const headers = { 'accept-language': request.headers.get('accept-language') ?? '' }
const languages = new Negotiator({ headers }).languages()
return match(languages, locales, defaultLocale)
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl
const hasLocale = locales.some(l => pathname.startsWith(`/${l}/`) || pathname === `/${l}`)
if (hasLocale) return
const locale = getLocale(request)
request.nextUrl.pathname = `/${locale}${pathname}`
return NextResponse.redirect(request.nextUrl)
}
Filer nestet under app/[språk]/, med en ordbøker/ mappen ved siden av layoutene og sidene dine. Rotlayouten mottar språk som en parameter og setter den på html tagg:
export default async function RootLayout({ children, params }) {
const { locale } = await params
return (
<html lang={locale}>
<body>{children}</body>
</html>
)
}
For oversettelser viser de offisielle dokumentene et rått ordboksmønster som ikke krever noe bibliotek:
const dictionaries = {
en: () => import('./dictionaries/en.json').then(m => m.default),
fr: () => import('./dictionaries/fr.json').then(m => m.default),
}
export const getDictionary = async (locale: string) => dictionaries[locale]()
Dette fungerer, men har ingen støtte for pluralisering eller interpolasjon. neste-intl dekker begge via getTranslations() og brukOversettelser() i Serverkomponenter og klientkomponenter henholdsvis.
Uansett behandles oversettelsesfiler på serveren, og bare den resulterende HTML-koden når nettleseren, så meldingsfilstørrelsen har ingen innvirkning på klientbuntstørrelsen.
For klientkomponenter, send oversatte strenger som props fra en overordnet serverkomponent der det er mulig. NextIntlClientProvider med et begrenset meldingsdelsett bare når en klientkomponent trenger å håndtere oversettelser direkte.
For en språkveksler gjengir en serverkomponent språketikettene mens en klientkomponent håndterer brukRuter() ringe:
// LocaleSwitcher.tsx (Server Component)
import LocaleSwitcherClient from './LocaleSwitcherClient'
export default function LocaleSwitcher({ locale }) {
return <LocaleSwitcherClient locale={locale} labels={{ en: 'English', fr: 'Français' }} />
}Klienten lytter halvveis etter endringer i valget og sender den nye lokale ruten:
// LocaleSwitcherClient.tsx
'use client'
import { useRouter } from 'next/navigation'
export default function LocaleSwitcherClient({ locale, labels }) {
const router = useRouter()
return (
<select value={locale} onChange={e => router.push(`/${e.target.value}`)}>
{Object.entries(labels).map(([value, label]) => (
<option key={value} value={value}>{label}</option>
))}
</select>
)
}Hvis du bruker Weglot , ingenting av dette gjelder. Weglot inkluderer en innebygd språkbytterwidget og krever ingen proxy-konfigurasjon eller mellomvare.
Ingen av ruterne håndterer flerspråklig SEO automatisk:
html-språk riktig, men dokumentasjonen sier at implementeringen av hreflang er «opp til deg».Med App Router bringer Metadata API deg nærmest automatisering. Definer lokale URL-er i genererMetadata via alternative språk objekt og Next.js automatiske injiseringer lenke rel="alternativ" hreflang="..." tagger:
export async function generateMetadata({ params: { locale } }) {
return {
alternates: {
languages: {
'en': 'https://example.com/en',
'fr': 'https://example.com/fr',
'de': 'https://example.com/de',
},
},
}
}Den manuelle delen handler om å samle inn riktig URL for hver språkvariant per side. Den logikken er din oppgave.
To andre ting krever manuell implementering uavhengig av hvilken ruter du bruker. Kanoniske URL-er må angis per språk for å unngå duplikatinnholdssignaler. Din sitemap.ts behov xhtml:lenke oppføringer for hver språkvariant på hver side.
På hreflang verdien i seg selv, bruk hreflang="en-US" når man målretter seg mot en bestemt region, og hreflang="en" når man retter seg mot alle engelsktalende. Å blande disse opp sender motstridende signaler til søkemotorer.
neste-intl legger til én delvis automatisering: proxyen injiserer automatisk hreflang Lenke svarhoder når du bruker lokalisert stinavnruting. Andre rutingskonfigurasjoner krever fortsatt manuell implementering.
Det er en betydelig mengde kontinuerlig vedlikehold etter hvert som nettstedet ditt vokser. Heldigvis, Weglot s reverse proxy håndterer alt automatisk på serveren, slik at oversatte sider er fullt indekserbare uten tilleggskode.
Faktisk, Weglot s reverse proxy håndterer alt som er dekket i forrige avsnitt automatisk: hreflang-tagger , oversatte URL-er, kanoniske tagger og generering av nettstedskart. Oversatte sider serveres på serversiden, slik at de er fullt indekserbare av søkemotorer.
⚠️ Weglot JavaScript-koden snippet Integrasjon gir ikke SEO-fordeler. Klientsideoversettelse kan ikke gjennomsøkes. Hvis SEO er viktig, kreves det oppsett av omvendt proxy .
En sekundær fordel er byggetid. Weglot serverer oversatte sider fra sitt eget CDN i stedet for å generere dem under bygging. Legger til 10 språk til en Weglot -drevet nettsted har ingen effekt på hvor lenge neste bygg tar.
Det riktige valget avhenger av hva du optimaliserer for.
Hvis du bygger på App Router og starter på nytt, neste-intl er standardvalget. Den dekker ruting, oversettelser, TypeScript-autofullføring og RSC-støtte i én pakke.
Hvis du er på Pages Router eller allerede har i18next i stacken din, react-i18next er minste motstands vei.
Hvis flerspråklig SEO og kontinuerlig oversettelseshåndtering er prioriteten, løser ingen av bibliotekene hele problemet. Du må fortsatt implementere hreflang, nettstedskart og en arbeidsflyt for å holde oversettelser oppdaterte etter hvert som innholdet endres. Weglot s reverse proxy håndterer alt dette automatisk.
Weglot og et bibliotek på komponentnivå utelukker ikke hverandre. Weglot opererer på HTML- og proxy-laget, slik at det kan sameksistere med hvilket som helst bibliotek komponentene dine bruker.
Hvis den tilnærmingen passer din situasjon, kan du sjekke ut Weglot JavaScript-integrasjonsside som et utgangspunkt og prøve vår 14-dagers gratis prøveperiode !
Den beste måten å forstå kraften i Weglot er å se det selv. Test det gratis og uten forpliktelser.
En demo-nettside er tilgjengelig i dashbordet ditt hvis du ikke er klar til å koble til nettstedet ditt ennå.