feat(i18n): adopt next/root-params - #1
Conversation
Next.js 16.3 exposes the `[locale]` root segment to Server Components via
`next/root-params`, which next-intl now reads directly. That removes the
`setRequestLocale` bookkeeping the app needed for static rendering and the
locale threading through every page's `params`.
- `i18n.tsx` resolves the locale from the root param, falling back to an
explicit one passed to `getTranslations({ locale })`
- `getLocaleAndPath` reads the locale itself instead of taking it as an
argument, so pages only destructure their own path segments
- `generateMetadata` reads the locale from the root param as well
- the root layout no longer receives `params`
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014bgJshfrV4RnhVz2csERpx
📦 Build Size ComparisonSummary
|
CI status: 11/13 green, 2 fork-infrastructure failuresBoth red checks are environmental to this fork and are not caused by the diff. Neither is fixable from the branch, so I've left them alone.
It fails at the action's very first step, before inspecting anything. This is a repo setting (Settings → Code security → Dependency graph), and in any case the diff changes no dependencies — no
That workflow's second step is Worth noting, because the two checks share the display name "Playwright Tests": the other one — Everything substantive passed:
The 0 B bundle delta is a reasonable sanity check on its own: this refactor removes Generated by Claude Code |
|
|
||
| // Gets the current full pathname for a given path | ||
| const [locale, pathname] = basePage.getLocaleAndPath(path, routeLocale); | ||
| const [locale, pathname] = await basePage.getLocaleAndPath(path); |
There was a problem hiding this comment.
No need to pass the routeLocale anymore since we can read from next/root-params within getLocaleAndPath.
| const RootLayout: FC<RootLayoutProps> = async ({ children, params }) => { | ||
| const { locale } = await params; | ||
| const RootLayout: FC<PropsWithChildren> = async ({ children }) => { | ||
| const locale = await getLocale(); |
There was a problem hiding this comment.
Using await getLocale() returns the returned locale from i18n.tsx—including potential defaults.
| export default getRequestConfig(async params => { | ||
| // An explicit locale passed to an awaitable API like `getTranslations({ locale })` | ||
| // wins, otherwise we read the `[locale]` segment of the root layout | ||
| let locale = params.locale ?? (await getRootLocale()); |
There was a problem hiding this comment.
This is the key: requestLocale is no longer needed, but we can read from next/root-params.
I've kept the behavior to read an override from a call site though, as this can be handy for Server Actions and Route Handlers (where next/root-params is not yet supported).
| // Forces the current locale to be the Default Locale | ||
| setRequestLocale(defaultLocale.code); | ||
| export const getLocaleAndPath = async (path = []) => { | ||
| const locale = (await getRootLocale()) ?? defaultLocale.code; |
There was a problem hiding this comment.
I've considered reading from await getLocale() here, but that would internally apply defaults. Might be safer to keep an additional call to next/root-params here so the validation below continues to work as-is.
| } | ||
|
|
||
| // Configures the current Locale to be the given Locale of the Request | ||
| setRequestLocale(locale); |
next/root-params
Description
Next.js 16.3 ships with
next/root-params, which is a significant improvement for users ofnext-intl.See the introductory blog post: Using next/root-params in Next.js 16.3
I went ahead to see how this integrates with nodejs.org, and it seems to work well!
Validation
I checked various languages and also different 404 states.
Related Issues
None.
Check List
pnpm formatto ensure the code follows the style guide.pnpm testto check if all tests are passing.pnpm buildto check if the website builds without errors.