fix(i18n): restore locale switching and release metadata

This commit is contained in:
Codex committed 2026-09-27 14:38:14 +00:00
1 parent a95d3652ca
commit 223ad634d7
7 files changed
+38 -18

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ const meta = new URL("../dist/.openai/", import.meta.url);
await rm(dist, { recursive: true, force: true });
await Promise.all([mkdir(server, { recursive: true }), mkdir(meta, { recursive: true })]);
const [rawIndexHtml, addonsJs, bootGuardJs, i18nJs, tasksJs, calendarJs, i18nRenderersJs, manifest, serviceWorker, icon, localeEn, localeZh] = await Promise.all([text("index.html"), text("addons.js"), text("boot-guard.js"), text("i18n.js"), text("tasks.js"), text("calendar.js"), text("i18n-renderers.js"), text("manifest.webmanifest"), text("service-worker.js"), text("life-os-icon.svg"), readFile(new URL("../public/locales/en.json", import.meta.url), "utf8"), readFile(new URL("../public/locales/zh-CN.json", import.meta.url), "utf8")]);
const release = "1.5.2";
const release = "1.5.3";
const indexHtml = rawIndexHtml.replace('src="addons.js"', `src="addons.js?v=${release}`).replace('src="tasks.js"', `src="tasks.js?v=${release}`).replace('src="calendar.js"', `src="calendar.js?v=${release}`);
await writeFile(new URL("assets.js", server), `export const indexHtml=${JSON.stringify(indexHtml)};\nexport const addonsJs=${JSON.stringify(addonsJs)};\nexport const bootGuardJs=${JSON.stringify(bootGuardJs)};\nexport const i18nJs=${JSON.stringify(i18nJs)};\nexport const localeEn=JSON.parse(${JSON.stringify(localeEn)});\nexport const localeZh=JSON.parse(${JSON.stringify(localeZh)});\nexport const localeEnJs=${JSON.stringify(`window.LifeOSLocales=window.LifeOSLocales||{};window.LifeOSLocales.en=${localeEn};`)};\nexport const localeZhJs=${JSON.stringify(`window.LifeOSLocales=window.LifeOSLocales||{};window.LifeOSLocales['zh-CN']=${localeZh};`)};\nexport const tasksJs=${JSON.stringify(tasksJs)};\nexport const calendarJs=${JSON.stringify(calendarJs)};\nexport const i18nRenderersJs=${JSON.stringify(i18nRenderersJs)};\nexport const manifest=${JSON.stringify(manifest)};\nexport const serviceWorker=${JSON.stringify(serviceWorker)};\nexport const icon=${JSON.stringify(icon)};\n`);
await copyFile(new URL("../worker/index.js", import.meta.url), new URL("index.js", server));
+20
View File
@@ -1,5 +1,6 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import vm from "node:vm";
const worker = await import(new URL("../dist/server/index.js", import.meta.url));
assert.equal(typeof worker.default?.fetch, "function");
const assets = await import(new URL("../dist/server/assets.js", import.meta.url));
@@ -33,7 +34,26 @@ for (const script of [assets.tasksJs, assets.calendarJs]) {
assert.doesNotMatch(script, /createTreeWalker|NodeFilter\.SHOW_TEXT/);
}
const source = await readFile(new URL("../public/index.html", import.meta.url), "utf8");
for (const [, inlineScript] of source.matchAll(/<script>([\s\S]*?)<\/script>/g)) new vm.Script(inlineScript);
assert.doesNotMatch(source, /localizeDynamicText|createTreeWalker|NodeFilter\.SHOW_TEXT|const ZH=/);
assert.match(source, /id==='system'\)window\.systemApp\(c\)/);
assert.match(source, /id==='today'\)window\.today\(c\)/);
assert.match(assets.i18nRenderersJs, /window\.setLanguage = value/);
assert.match(assets.i18nRenderersJs, /window\.renderAll\(\)/);
assert.doesNotMatch(source, /Version 0\.1|Schema v1/);
const langSource = source.match(/function browserLanguage\(\).*?function i18n\(key/)[0].replace(/function i18n\(key[\s\S]*$/, "");
let preferences = { language: "auto", languageMode: "auto" };
const languageContext = vm.createContext({ navigator: { languages: ["zh-CN"], language: "zh-CN" }, settings: () => preferences });
vm.runInContext(langSource, languageContext);
assert.equal(languageContext.lang(), "zh", "auto mode follows Chinese browser language");
languageContext.navigator.languages = ["en-US"];
assert.equal(languageContext.lang(), "en", "auto mode follows English browser language");
preferences = { language: "zh", languageMode: "manual" };
assert.equal(languageContext.lang(), "zh", "manual Chinese choice overrides browser language");
preferences = { language: "en", languageMode: "manual" };
assert.equal(languageContext.lang(), "en", "manual English choice overrides browser language");
preferences = { language: "zh" };
assert.equal(languageContext.lang(), "zh", "legacy manual preference survives settings migration");
const zhLogin = await worker.default.fetch(new Request("https://life-os.test/", { headers: { "accept-language": "zh-CN,zh;q=0.9" } }), {});
assert.match(await zhLogin.text(), /登录 ChatGPT/);
const enLogin = await worker.default.fetch(new Request("https://life-os.test/", { headers: { "accept-language": "en-US,en;q=0.9" } }), {});