Capítulo 49 de 456
Next.js supports internationalized routing (sub-path or domain based) and localized content, letting you route requests by locale and load translated dictionaries per request.
en-US, nl-NL, nl)./fr/products.my-site.fr/products.app/[lang] segment: all special files nested under a dynamic [lang] segment so the router forwards lang to every layout/page (including the root layout).import().next/root-params: exports a getter per dynamic segment above the root layout (e.g. lang()), letting server code read the locale without prop drilling; works in Server Components and server-side utilities only, not Client Components, Server Actions, or Route Handlers.generateStaticParams: used on a layout/page (commonly the root layout) to statically generate routes for a set of locales.// proxy.js - detect locale from Accept-Language and redirect
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import { NextResponse } from "next/server";
let locales = ['en-US', 'nl-NL', 'nl']
function getLocale(request) { /* use match()/Negotiator */ }
export function proxy(request) {
const { pathname } = request.nextUrl
const pathnameHasLocale = locales.some(
(locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
)
if (pathnameHasLocale) return
const locale = getLocale(request)
request.nextUrl.pathname = `/${locale}${pathname}`
return NextResponse.redirect(request.nextUrl)
}
export const config = {
matcher: ['/((?!_next).*)'],
}
// app/[lang]/dictionaries.ts
import 'server-only'
const dictionaries = {
en: () => import('./dictionaries/en.json').then((m) => m.default),
nl: () => import('./dictionaries/nl.json').then((m) => m.default),
}
export type Locale = keyof typeof dictionaries
export const hasLocale = (locale: string): locale is Locale => locale in dictionaries
export const getDictionary = async (locale: Locale) => dictionaries[locale]()
// app/[lang]/dictionaries.ts com next/root-params
import { lang } from 'next/root-params'
import { notFound } from 'next/navigation'
export const getDictionary = async () => {
const locale = await lang()
if (!hasLocale(locale)) notFound()
return dictionaries[locale]()
}
next/root-params elimina a necessidade de passar lang manualmente por camadas de componentes.lang: passar lang manualmente por várias camadas quando next/root-params resolve isso diretamente em qualquer Server Component.lang sem checar hasLocale pode causar erro de runtime em vez de um 404 controlado.Accept-Language (via negotiator + @formatjs/intl-localematcher) no proxy para decidir o locale preferido.app/[lang] para o router forwardar o parâmetro automaticamente.import() dinâmico mantêm o bundle do cliente enxuto, pois rodam só no servidor.next/root-params evita prop drilling, mas só funciona em Server Components e utilitários server-side.generateStaticParams no layout raiz gera rotas estáticas por locale.