You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
perf: set up the i18n server context on first use - #4174
The server plugin builds the i18n context in the request hook, so every request pays for it. That includes /_nuxt assets, files from public/, API routes, and the internal $fetch behind useFetch. Most of the cost is useRuntimeConfig(event), which in Nitro 2 copies the whole config and checks env vars for every key.
Now the context is set up the first time something needs it: render:before for pages, the messages route, and the server locale detector. Pages cost the same as before, because Nuxt's renderer calls useRuntimeConfig(event) for them anyway.
From the repro: Nuxt 4.6.2, Nitro 2, i18n 10.6.0, 3 locales, production build. Server CPU per request, median of 6 alternating rounds of 2000 requests:
request
before
after
API route
0.448 ms
0.157 ms
public/robots.txt
0.547 ms
0.305 ms
/_nuxt asset
1.060 ms
0.821 ms
page
1.743 ms
1.557 ms (noise)
The first three dropped in every round. verify.mjs also checks that the context is no longer set up for those requests, and that pages still render their translations. On a bigger app with @nuxt/ui and Pinia, the HTML stayed byte-identical on 13 paths.
We've flagged this as a potential contribution without a human behind it. We welcome the thoughtful use of AI tools when contributing to Nuxt i18n, but ask all contributors to follow two core principles:
Never let an LLM speak for you - all comments, issues, and PR descriptions should be written in your own words, reflecting your own understanding.
Never let an LLM think for you - only submit contributions you fully understand and can explain.
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.
Walkthrough
The server plugin no longer initializes i18n context on every request. It reuses an existing context or initializes one in the render hook. The message route and locale detector also initialize context when it is absent. The change removes the useI18nContext and fetchMessages helpers. A test checks that an API request without prior initialization reports initialized: false.
No concrete current-head failure was established; the lazy initialization paths are consistent and ready for normal checks.
Pre-merge checks: 4 · 1
Failed checks: 1 warning
Check name
Status
Explanation
Resolution
Docstring Coverage
Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 5 files.
Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed checks: 4 passed
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
The title clearly and concisely describes the main change: initializing the i18n server context on first use instead of on every request.
Linked Issues check
[#4144] Requirement: avoid i18n context setup on requests that do not use i18n (for example /_nuxt assets and API routes), and leave SSR requests unaffected. The PR removes the per-request Nitro `requ…
Out of Scope Changes check
The changed files are plugin.ts, messages.ts, locale-detector.ts, and context.ts. Each one moves or removes context setup, which is the scope of #4144. The removed exports useI18nContext and `fetchM…
Full details: Linked Issues check
Explanation
[#4144] Requirement: avoid i18n context setup on requests that do not use i18n (for example /_nuxt assets and API routes), and leave SSR requests unaffected. The PR removes the per-request Nitro request hook that called initializeI18nContext. Context setup now runs on demand: in render:before for pages (including the prerender path), in the messages route, and in the server locale detector, each when no context exists. The new spec fixture /api/i18n-context asserts { initialized: false }, which supports that an API route does not initialize context. Pages still initialize context before rendering, so SSR behavior is preserved. The reduction in CPU cost is reported by the author as benchmark data; I did not verify those numbers. Evidence limit: file-level diffs for plugin.ts, messages.ts, and locale-detector.ts were unavailable. Their behavior is taken from the PR change summary. At head, src/runtime/server/context.ts contains initializeI18nContext and no longer contains useI18nContext or fetchMessages, which matches the summary. Asset 404 behavior is handled by Nitro before the renderer and needs no i18n change. All requirements in #4144 are coding requirements. No non-coding requirements apply.
Full details: Out of Scope Changes check
Explanation
The changed files are plugin.ts, messages.ts, locale-detector.ts, and context.ts. Each one moves or removes context setup, which is the scope of #4144. The removed exports useI18nContext and fetchMessages in context.ts have no remaining callers in the changed-file list. Their removal follows from the locale detector and messages route no longer depending on them. The spec fixture and spec assertion support the requirement that API routes do not initialize context. The PR description notes a conflict with #4088 for Nitro 3 and Nuxt 5, but this is a note, not a code change. Limit: the file-level diffs were unavailable, so the absence of other callers of the removed exports relies on the complete changed-file list, not on a repository search.
Finishing Touches
🧪 Generate unit tests (beta)
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
This branch has not been deployed
No deployments
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
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.
🔗 Linked issue
Resolves #4144
Repro with a before and after: https://github.com/onmax/repros/tree/repro/i18n-4144/i18n-4144 (
node verify.mjs && node bench.mjs)📚 Description
The server plugin builds the i18n context in the
requesthook, so every request pays for it. That includes/_nuxtassets, files frompublic/, API routes, and the internal$fetchbehinduseFetch. Most of the cost isuseRuntimeConfig(event), which in Nitro 2 copies the whole config and checks env vars for every key.Now the context is set up the first time something needs it:
render:beforefor pages, the messages route, and the server locale detector. Pages cost the same as before, because Nuxt's renderer callsuseRuntimeConfig(event)for them anyway.From the repro: Nuxt 4.6.2, Nitro 2, i18n 10.6.0, 3 locales, production build. Server CPU per request, median of 6 alternating rounds of 2000 requests:
public/robots.txt/_nuxtassetThe first three dropped in every round.
verify.mjsalso checks that the context is no longer set up for those requests, and that pages still render their translations. On a bigger app with @nuxt/ui and Pinia, the HTML stayed byte-identical on 13 paths.