v3.24.0
Date: 2026-07-30
Version: v3.24.0

Node production builds no longer embed translation payloads as Nitro serverAssets / Rollup raw: (multi‑GB build RSS on large catalogs). SSR reads the same /{apiBaseUrl}/{page}/{locale}/data.json tree the client fetches — from public/ via readFile. Edge keeps a Nitro embed and should prefer mode: 'source'.
What's New?
Node: SSR from public/<apiBaseUrl>
- Node presets that serve
public/from disk do not register NitroserverAssets. - Payloads are copied to
public/<apiBaseUrl>(default_locales) as{page}/{locale}/data.json. - SSR loads them through
#i18n-internal/payload-source→readFile(prod path next to.output/server). translationPayloads.serverAssets: truestill means “local SSR” and forces that public copy even ifpublicAssetsis false.
Playground (vs previous serverAssets embed): ~1.25 GB / ~6–7 s / raw=0 vs ~3 GB / ~13 s / ~170 raw chunks.
Edge: serverAssets only when needed
- Edge (
nitro.node === false) still embeds via NitroserverAssets(assets:i18n) with the same layout asmode. - Edge does not force a public copy — set
publicAssets: truefor CDN/static. - Warns when Edge +
mode: 'premerged'(prefermode: 'source'for large catalogs).
publicDir aligns with client URLs
translationPayloads.publicDirdefaults toapiBaseUrl(nottranslationDir).- Premerged public/Edge tree is
{page}/{locale}/data.json, matching$fetch('/_locales/...'). - Module defaults no longer set nested
publicAssets: true(Nuxt deep-merge was forcing public copy even formode: 'source').
See Module options — translationPayloads, Deployment — serverless and Edge, and Cache & Storage Architecture.
Breaking Changes
- No dictionaries in the Nuxt SSR HTML payload.
payload.data['i18n-ssr-chunks'],setSsrChunk, andseedFromSsrChunksare removed. Same default posture as@nuxtjs/i18n(experimental.preload: false): server keeps translations in memory for SSR; the client loads/{apiBaseUrl}/.../data.jsonduring plugin setup (await switchContext). prerenderRoutesdefaults tofalse. Opt in only if you need Nitro to materialize handler routes whenpublicAssetsdid not already write the tree (premergedpublicAssetsalready emits{page}/{locale}/data.json).publicDirdefault isapiBaseUrl, nottranslationDir. Static output moves from e.g.public/locales/...topublic/_locales/{page}/{locale}/data.jsonunless you setpublicDirexplicitly.- Premerged storage layout is now
{page}/{locale}/data.json(waspages/{page}/{locale}.json). Anything that read Nitro/storage keys or copied trees by the old shape must update. - On Node,
serverAssets: trueno longer means Nitro embed — it means local SSR via the public copy. True Rollupraw:embed remains Edge-only.
Migration
- Remove any code that read
payload.data['i18n-ssr-chunks']or calledseedFromSsrChunks/setSsrChunk. - For pure static hosts: keep default premerged +
publicAssets(files land at/_locales/.../data.json), or setprerenderRoutes: true/ host payloads on a CDN. - For Cloudflare / other Edge: set
translationPayloads: { mode: 'source' }on large catalogs; addpublicAssets: trueonly if you need a static/CDN copy. - If you depended on payloads under
public/<translationDir>, settranslationPayloads.publicDiror point tooling atpublic/<apiBaseUrl>.
Fix: skip disabled locales in premerged public payloads
preMergeLocales now writes {page}/{locale}/data.json only for locales passed into the merge (build-time locale.disabled: true is omitted). Previously every JSON locale on disk was copied to public/, so Nitro static served disabled locales with 200 and bypassed the handler. Runtime disabledLocales still cannot un-publish files already built — use locale.disabled at build when publicAssets / Node public SSR copy is on.
Why It Matters
- Node builds stay lean: no multi‑GB Rollup
raw:spike from translation catalogs. - Public files and client
$fetchURLs share one path layout — static hosting works without a special remap. - Edge can still embed compact
sourcepayloads without forcing a duplicate public tree.
Full changelog will be published with the release on GitHub.