fix(csr): preserve translations across navigation
This commit is contained in:
@@ -317,7 +317,7 @@
|
|||||||
},
|
},
|
||||||
"packages/csr": {
|
"packages/csr": {
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.20",
|
"version": "0.8.21",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@wrnexus/core": "workspace:*",
|
"@wrnexus/core": "workspace:*",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@wrnexus/csr",
|
"name": "@wrnexus/csr",
|
||||||
"version": "0.8.20",
|
"version": "0.8.21",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
|||||||
@@ -380,6 +380,27 @@ export const NAV_RUNTIME = String.raw`
|
|||||||
var current = window.__wrnI18n || {};
|
var current = window.__wrnI18n || {};
|
||||||
var translator = current.t;
|
var translator = current.t;
|
||||||
var setter = current.set;
|
var setter = current.set;
|
||||||
|
function mergeCatalog(base, update) {
|
||||||
|
var output = {};
|
||||||
|
Object.keys(base && typeof base === "object" ? base : {}).forEach(function (key) {
|
||||||
|
var value = base[key];
|
||||||
|
output[key] = value && typeof value === "object" && !Array.isArray(value)
|
||||||
|
? mergeCatalog(value, {})
|
||||||
|
: value;
|
||||||
|
});
|
||||||
|
Object.keys(update && typeof update === "object" ? update : {}).forEach(function (key) {
|
||||||
|
var left = output[key];
|
||||||
|
var right = update[key];
|
||||||
|
output[key] = left && right && typeof left === "object" && typeof right === "object" && !Array.isArray(left) && !Array.isArray(right)
|
||||||
|
? mergeCatalog(left, right)
|
||||||
|
: right;
|
||||||
|
});
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
if (current.lang && current.lang === incoming.lang) {
|
||||||
|
incoming.messages = mergeCatalog(current.messages, incoming.messages);
|
||||||
|
incoming.fallbackMessages = mergeCatalog(current.fallbackMessages, incoming.fallbackMessages);
|
||||||
|
}
|
||||||
window.__wrnI18n = incoming;
|
window.__wrnI18n = incoming;
|
||||||
if (translator) window.__wrnI18n.t = translator;
|
if (translator) window.__wrnI18n.t = translator;
|
||||||
if (setter) window.__wrnI18n.set = setter;
|
if (setter) window.__wrnI18n.set = setter;
|
||||||
|
|||||||
@@ -161,6 +161,36 @@ test("synchronizes and rebinds i18n data during client navigation", async () =>
|
|||||||
expect(boundRoot).toBe(win.document.getElementById("app"));
|
expect(boundRoot).toBe(win.document.getElementById("app"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("preserves same-language translations when an incoming navigation catalog is partial", async () => {
|
||||||
|
install(`<div id="app"><a href="/about" id="lnk">About</a></div>`);
|
||||||
|
win.__wrnI18n = {
|
||||||
|
lang: "en",
|
||||||
|
messages: { navigation: { home: "Home" }, footer: { contact: "Contact" } },
|
||||||
|
fallbackMessages: {},
|
||||||
|
};
|
||||||
|
win.__wrnLang = {
|
||||||
|
bind: (root: ParentNode) => {
|
||||||
|
root.querySelectorAll("[data-t]").forEach((node) => {
|
||||||
|
const parts = String(node.getAttribute("data-t") || "").split(".");
|
||||||
|
let value: any = win.__wrnI18n.messages;
|
||||||
|
for (const part of parts) value = value?.[part];
|
||||||
|
node.textContent = typeof value === "string" ? value : node.getAttribute("data-t");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
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>` +
|
||||||
|
`</body></html>`;
|
||||||
|
|
||||||
|
win.document.getElementById("lnk").click();
|
||||||
|
await flush();
|
||||||
|
|
||||||
|
expect(win.__wrnI18n.messages.navigation.home).toBe("Home");
|
||||||
|
expect(win.__wrnI18n.messages.footer.contact).toBe("Contact");
|
||||||
|
expect(win.document.querySelector("[data-t]")?.textContent).toBe("Home");
|
||||||
|
});
|
||||||
|
|
||||||
test("unmounts and remounts package runtimes during client navigation", async () => {
|
test("unmounts and remounts package runtimes during client navigation", async () => {
|
||||||
install(
|
install(
|
||||||
`<div id="app"><div data-wrnexus-runtime="captcha">Old</div><a href="/next" id="lnk">Next</a></div>`,
|
`<div id="app"><div data-wrnexus-runtime="captcha">Old</div><a href="/next" id="lnk">Next</a></div>`,
|
||||||
|
|||||||
Reference in New Issue
Block a user