Multilingual support
Multilingual Support
When to Use
Support multiple languages in your Next.js site backed by multilingual Drupal content.
Steps
1. Apply Decoupled Router patch
See Drupal Setup section for patch details. Required for language resolution.
2. Configure locales (App Router)
The Pages Router i18n key in next.config.js does not work with the App Router — it is silently ignored. Instead, define your locales in a shared config and route localized pages through a [lang] dynamic segment.
// lib/i18n.ts
export const locales = ["en", "es", "fr"] as const
export const defaultLocale = "en"
export type Locale = (typeof locales)[number]
Place localized routes under an app/[lang]/ segment (e.g. app/[lang]/[...slug]/page.tsx). Optionally add a middleware.ts that redirects / to /${defaultLocale} and negotiates the visitor's preferred language from the Accept-Language header.
3. Use locale parameter when fetching
const article = await drupal.getResource(
"node--article",
uuid,
{
locale: "es",
defaultLocale: "en",
}
)
4. Configure path aliases per language
In Drupal, configure path patterns for each language at /admin/config/search/path/patterns.
5. Translate path for dynamic routes
// app/[lang]/[...slug]/page.tsx
import { defaultLocale } from "@/lib/i18n"
// `params` is a Promise in Next.js 15+ and includes the [lang] segment.
export default async function Page({
params,
}: {
params: Promise<{ lang: string; slug: string[] }>
}) {
const { lang, slug } = await params
const path = await drupal.translatePath(`/${slug.join("/")}`, {
locale: lang,
defaultLocale,
})
const node = await drupal.getResource(
path.jsonapi.resourceName,
path.entity.uuid,
{
locale: lang,
defaultLocale,
}
)
return <article>{node.title}</article>
}
Decision Points
| Decision | When | Impact |
|---|---|---|
| Path prefix strategy | Setup | /es/about vs /about?lang=es |
| Language fallback | Content gaps | Show default language vs 404 |
| Translation workflow | Content strategy | Sync vs independent translation |
Common Mistakes
- Using the
next.config.jsi18nkey with App Router — It is silently ignored; you get no localized routing. WHY:i18nconfig is a Pages Router feature. Use a[lang]route segment instead. - Not applying Decoupled Router patch — Language resolution fails. WHY: Drupal can't resolve paths in non-default languages.
- Forgetting locale in translatePath — Always returns default language. WHY: Drupal needs explicit locale for routing.
- Inconsistent locale parameter — Mixed language content. WHY: Must pass locale to all drupal.getResource calls.
- Missing path aliases per language — 404 errors. WHY: Each language needs its own path configuration.
See Also
- Drupal Setup
- Building Pages
- Troubleshooting