fix(i18n): ship i18n data as a JSON block so CSP cannot block it

window.__wrnI18n was undefined in development: the payload shipped as an
executable inline script, and a document's CSP nonce is fixed at load, so
any such script arriving from a later response is blocked. Client
translations and language switching silently had no data.

The payload is now a type="application/json" block, which the browser
never executes and script-src therefore never applies to. The i18n
runtime, CSR navigation, and HMR all read the block instead of matching
window.__wrnI18n= with a regex.

Pages now render zero executable inline scripts, so an inline script-src
violation is structurally impossible rather than merely unobserved. Zero
framework JavaScript on island-free routes is unaffected: the block is
inert data, and nothing loads to read it unless the page needs it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 19:44:28 +05:30
co-authored by Claude Opus 5
parent e819c5739e
commit 5dbcc5b85d
7 changed files with 78 additions and 32 deletions
+2 -7
View File
@@ -368,15 +368,10 @@ export const NAV_RUNTIME = String.raw`
}
function syncI18n(nextDocument) {
var script = Array.prototype.find.call(
nextDocument.querySelectorAll("script:not([src])"),
function (node) { return /^window\.__wrnI18n=/.test(String(node.textContent || "").trim()); },
);
var script = nextDocument.querySelector('script[type="application/json"][data-wrn-i18n]');
if (!script) return;
var match = /^window\.__wrnI18n=([\s\S]*);\s*$/.exec(String(script.textContent || "").trim());
if (!match) return;
try {
var incoming = JSON.parse(match[1]);
var incoming = JSON.parse(String(script.textContent || "{}"));
var current = window.__wrnI18n || {};
var translator = current.t;
var setter = current.set;
+2 -2
View File
@@ -148,7 +148,7 @@ test("synchronizes and rebinds i18n data during client navigation", async () =>
win.__wrnLang = { bind: (root: unknown) => (boundRoot = root) };
nextHtml =
`<html lang="mr"><body><div id="app"><p data-t="home.title">नवीन</p></div>` +
`<script>window.__wrnI18n={"lang":"mr","messages":{"home":{"title":"नवीन"}},"fallbackMessages":{}};</script>` +
`<script type="application/json" data-wrn-i18n>{"lang":"mr","messages":{"home":{"title":"नवीन"}},"fallbackMessages":{}}</script>` +
`</body></html>`;
win.document.getElementById("lnk").click();
@@ -180,7 +180,7 @@ test("preserves same-language translations when an incoming navigation catalog i
};
nextHtml =
`<html lang="en"><body><div id="app"><p data-t="navigation.home">navigation.home</p></div>` +
`<script>window.__wrnI18n={"lang":"en","messages":{},"fallbackMessages":{}};</script>` +
`<script type="application/json" data-wrn-i18n>{"lang":"en","messages":{},"fallbackMessages":{}}</script>` +
`</body></html>`;
win.document.getElementById("lnk").click();