Skip to content

feat(i18n): adopt next/root-params - #1

Closed
amannn wants to merge 3 commits into
mainfrom
claude/next-root-params
Closed

feat(i18n): adopt next/root-params#1
amannn wants to merge 3 commits into
mainfrom
claude/next-root-params

Conversation

@amannn

@amannn amannn commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Description

Next.js 16.3 ships with next/root-params, which is a significant improvement for users of next-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

  • I have read the Contributing Guidelines and made commit messages that follow the guideline.
  • I have run pnpm format to ensure the code follows the style guide.
  • I have run pnpm test to check if all tests are passing.
  • I have run pnpm build to check if the website builds without errors.
  • I've covered new added functionality with unit tests if necessary.

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
@github-actions

Copy link
Copy Markdown

📦 Build Size Comparison

Summary

Metric Value
Old Total First Load JS 7.16 MB
New Total First Load JS 7.16 MB
Delta 0 B (0.00%)

amannn commented Aug 13, 2026

Copy link
Copy Markdown
Owner Author

CI status: 11/13 green, 2 fork-infrastructure failures

Both 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.

dependency-review / dependency-review

Dependency review is not supported on this repository. Please ensure that Dependency graph
is enabled along with GitHub Advanced Security on private repositories

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 package.json, no pnpm-lock.yaml. next@16.3.0-preview.9 and next-intl@4.13.4 were already installed.

Playwright Tests (the playwright.yml job)

Could not find any deployments for actor vercel[bot], retrying (attempt 30 / 30)
no vercel deployment found, exiting...

That workflow's second step is wait-for-vercel-preview, which polls for 5 minutes for a Vercel preview deployment. This fork has no Vercel integration, so no preview is ever created and the job dies there — before Playwright browsers are even installed. No test ever ran, so this is not a test failure.

Worth noting, because the two checks share the display name "Playwright Tests": the other one — playwright-cloudflare-open-next.ymlpassed. That job needs no preview URL; it builds the site locally via open-next and runs the real E2E suite (pnpm --filter=@node-core/platform-cloudflare test:e2e). So the end-to-end suite did execute against this change, and it's green.

Everything substantive passed:

Check
Build on ubuntu-latest
Build on windows-latest
Quality checks (lint / types / prettier)
Tests
Playwright Tests (Cloudflare open-next, real E2E)
CodeQL (javascript + typescript)
zizmor / Zizmor Security Analysis
Compare Bundle Size ✅ 0 B delta (0.00%)

The 0 B bundle delta is a reasonable sanity check on its own: this refactor removes setRequestLocale bookkeeping without shifting anything across the server/client boundary.


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);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using await getLocale() returns the returned locale from i18n.tsx—including potential defaults.

Comment thread apps/site/i18n.tsx
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());

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer needed.

@amannn amannn changed the title feat(i18n): adopt next/root-params feat(i18n): adopt next/root-params Aug 14, 2026
@amannn

amannn commented Aug 14, 2026

Copy link
Copy Markdown
Owner Author

nodejs#9105

@amannn amannn closed this Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant