@@ -316,11 +316,11 @@
后台任务
-
🌱 EMRG 刚刚完成一次自我进化!
-
它学会了新的东西,变得更好用了。
+
🌱 EMRG 刚刚完成一次自我进化!
+
它学会了新的东西,变得更好用了。
-
-
+
+
diff --git a/emrg/gui/renderer/js/i18n.js b/emrg/gui/renderer/js/i18n.js
index aa82ba2..259efa2 100644
--- a/emrg/gui/renderer/js/i18n.js
+++ b/emrg/gui/renderer/js/i18n.js
@@ -20,6 +20,8 @@ const I18N = (() => {
"sidebar.newChat": "+ 新对话",
"sidebar.newChatTitle": "新对话 (⌘N)",
"sidebar.settings": "设置",
+ "sidebar.statusTitle": "连接状态",
+ "sidebar.backToBottom": "回到底部",
// 空状态欢迎屏
"empty.hello": "你好,我是 EMRG",
@@ -52,10 +54,14 @@ const I18N = (() => {
"settings.availableModels": "可用模型",
"settings.addModel": "+ 添加模型",
"settings.name": "名称",
+ "settings.modelNamePlaceholder": "如 deepseek-v3",
"settings.modelId": "模型 ID(选填)",
"settings.modelIdPlaceholder": "默认同名称",
"settings.vision": "支持图片",
"settings.cancel": "取消",
+ "settings.aboutTitle": "关于",
+ "settings.aboutDesc": "EMRG 是一个会自我进化的 AI 智能体——每次改进都会自动汇报,你可以随时在这里看到它的成长。",
+ "settings.recentTitle": "最近改进",
"settings.saveModel": "保存模型",
"settings.defaultHint": "点左侧圆点可设为默认模型,切换后下一条消息即生效",
"settings.groupWorkdir": "工作目录",
@@ -147,12 +153,14 @@ const I18N = (() => {
"copy.aboutEvolution": "EMRG 已自我成长 {n} 次,感谢你的每一次反馈",
"copy.aboutEvolutionEmpty": "EMRG 正在成长中",
// WorkBuddy P3(#501):成长卡 + 进化 toast
+ "copy.growthCardTitle": "EMRG 每次自我改进都会自动汇报",
"copy.growthCount": "已自我进化 {n} 次",
"copy.growthCountPrefix": "已自我进化",
"copy.times": "次",
"copy.growthNote": "边工作边学习,越用越懂你",
"copy.evolutionToastTitle": "EMRG 刚刚完成一次自我进化!",
"copy.evolutionToastMsg": "这是它的第 {n} 次自我改进,现在更好用了。",
+ "copy.evolutionToastMsgStatic": "它学会了新的东西,变得更好用了。",
"copy.evolutionToastSee": "去看看",
"copy.evolutionToastDismiss": "知道了",
@@ -272,6 +280,8 @@ const I18N = (() => {
"sidebar.newChat": "+ New chat",
"sidebar.newChatTitle": "New chat (⌘N)",
"sidebar.settings": "Settings",
+ "sidebar.statusTitle": "Connection status",
+ "sidebar.backToBottom": "Back to bottom",
// Empty state
"empty.hello": "Hi, I'm EMRG",
@@ -304,10 +314,14 @@ const I18N = (() => {
"settings.availableModels": "Available models",
"settings.addModel": "+ Add model",
"settings.name": "Name",
+ "settings.modelNamePlaceholder": "e.g. deepseek-v3",
"settings.modelId": "Model ID (optional)",
"settings.modelIdPlaceholder": "Defaults to name",
"settings.vision": "Supports images",
"settings.cancel": "Cancel",
+ "settings.aboutTitle": "About",
+ "settings.aboutDesc": "EMRG is a self-evolving AI agent — it reports every improvement, and you can watch it grow right here.",
+ "settings.recentTitle": "Recent improvements",
"settings.saveModel": "Save model",
"settings.defaultHint": "Click the dot on the left to set the default model — takes effect on the next message",
"settings.groupWorkdir": "Working directory",
@@ -399,12 +413,14 @@ const I18N = (() => {
"copy.aboutEvolution": "EMRG has self-evolved {n} times — thanks for every bit of feedback",
"copy.aboutEvolutionEmpty": "EMRG is still growing",
// WorkBuddy P3 (#501): growth card + evolution toast
+ "copy.growthCardTitle": "EMRG reports every self-improvement automatically",
"copy.growthCount": "Self-evolved {n} times",
"copy.growthCountPrefix": "Self-evolved",
"copy.times": "times",
"copy.growthNote": "Learning as I work — getting better with use",
"copy.evolutionToastTitle": "EMRG just completed a self-evolution!",
"copy.evolutionToastMsg": "That's its {n}th self-improvement — it's even better now.",
+ "copy.evolutionToastMsgStatic": "It learned something new and is even better now.",
"copy.evolutionToastSee": "See details",
"copy.evolutionToastDismiss": "Got it",
diff --git a/emrg/gui/test/i18n.test.js b/emrg/gui/test/i18n.test.js
index 3a00a0d..bcf2b7a 100644
--- a/emrg/gui/test/i18n.test.js
+++ b/emrg/gui/test/i18n.test.js
@@ -161,3 +161,33 @@ test("Stage2:成长卡/关于区静态文案键(#501 吸收)", () => {
const { ctx: zh } = makeSandbox({ navigator: { language: "zh-CN" } });
assert.strictEqual(evalIn(zh, 'I18N.t("copy.growthCount", { n: 7 })'), "已自我进化 7 次");
});
+
+// ── Stage 3(cycle 20260806-225341):index.html 无遗漏硬编码中文 ──
+test("Stage3:index.html 中文字符串必须带 data-i18n(防漏网回归)", () => {
+ const html = fs.readFileSync(path.join(__dirname, "..", "renderer", "index.html"), "utf8");
+ const cjk = /[\u4e00-\u9fff]/;
+ const leaks = [];
+ for (const [i, line] of html.split("\n").entries()) {
+ const s = line.trim();
+ if (!cjk.test(s)) continue; // 无中文
+ if (s.startsWith("