fix: setRequestLocale before next-intl APIs in all generateMetadata (+ lint rule)#18811
Draft
pettinarip wants to merge 1 commit into
Draft
fix: setRequestLocale before next-intl APIs in all generateMetadata (+ lint rule)#18811pettinarip wants to merge 1 commit into
pettinarip wants to merge 1 commit into
Conversation
… lint rule Every `generateMetadata` in app/ called a next-intl API (getTranslations directly and/or via the getMetadata/getMdMetadata helpers) without first calling `setRequestLocale(locale)`. Without it, next-intl reads the locale from request headers, opting the route into dynamic rendering and throwing "Page changed from static to dynamic at runtime, reason: headers" for on-demand params (invalid-locale/unknown-slug bot probes not covered by generateStaticParams). Prerendered locales were unaffected (built with no headers), so only a few routes alerted in prod, but the gap was latent across ~54 pages. - Add `setRequestLocale(locale)` at the top of every generateMetadata that uses a next-intl API. - Add a local ESLint rule (local-rules/require-setrequestlocale, error on app/**) that flags any generateMetadata calling a next-intl API before setRequestLocale, so this can't regress. Overlaps recovery PRs #18785 #18797 #18798 #18800 on those 4 files (same one-line addition); trivial to reconcile whichever merges first.
✅ Deploy Preview for ethereumorg ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
Every
generateMetadataunderapp/calls a next-intl API —getTranslations(...)directly and/or thegetMetadata/getMdMetadatahelpers (which callgetTranslations("common")internally) — without first callingsetRequestLocale(locale).next-intl's request config (
src/i18n/request.ts) resolves the locale viarequestLocale, which reads request headers unlesssetRequestLocalehas primed the per-request cache. So anygenerateMetadatathat runs a next-intl API beforesetRequestLocaleopts the route into dynamic rendering and, for params rendered on-demand (invalid-locale / unknown-slug bot probes not covered bygenerateStaticParams), Next.js throws:Prerendered locales are built with no headers, so they were unaffected — which is why only a handful of routes actually alerted in production while the gap was latent across ~54 pages.
Why not a central fix?
There's no single choke point:
getMetadatareceiveslocalebut callsgetTranslations("common")(locale-less), and pages also callgetTranslations("page-x")directly beforegetMetadatato build the title. Fixing only the helper leaves the direct call reading headers.setRequestLocale(locale)at the top of eachgenerateMetadataneutralizes both paths at once, which is the pattern next-intl documents for static rendering.Changes
setRequestLocale(locale)at the top of everygenerateMetadatainapp/that uses a next-intl API (before the first next-intl call).local-rules/require-setrequestlocale(error onapp/**) viaeslint-plugin-local-rules. It flags anygenerateMetadatathat calls a next-intl API (getTranslations,getMessages,getMetadata,getMdMetadata, …) beforesetRequestLocale, so this can't regress.Verification
pnpm type-check✅pnpm lint(full repo) ✅ — 0 errorsRuleTester(valid: correct order / no-intl / non-generateMetadata; invalid: missing / wrong-order / helper-only) and confirmed firing on a scratch page.Relationship to the recovery PRs
Overlaps recovery PRs #18785, #18797, #18798, #18800 on those 4 files (identical one-line addition in
generateMetadata). Whichever merges first, reconciliation is trivial. Note: this PR intentionally scopes togenerateMetadataonly — the page-body ordering fixes for wallets/videos live in those recovery PRs.🤖 Generated with Claude Code