fix(#618): translate the release toast for zh-CN

The toast every user sees once per release had no zh-CN entries, so a
Chinese interface showed it, button included, in English. The button
gets an entry and the frame a translateDynamic pattern that keeps the
version, the "(+N more)" count and the highlights (those come from
CHANGELOG.md and stay English). Tested through the real i18n.js in JSDOM,
plus a pin on the strings settings-ui.js builds, which the pattern
depends on.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer committed 2026-10-16 01:28:54 +02:00
1 parent 71439c525b
commit a61db218ee
2 files changed
+37

No files matched your search

+6
View File
@@ -798,6 +798,8 @@
// Dynamic common status / toasts
'Settings saved': '设置已保存',
// The once-per-release toast (settings-ui.js checkWhatsNew); its highlights stay English.
"See what's new": '查看更新内容',
'Settings applied': '设置已应用',
'Save and keep Settings open': '保存并保持设置打开',
'Settings saved locally': '设置已保存到本机',
@@ -1244,6 +1246,10 @@
[/^Update to v(.+)$/, (_m, version) => `更新到 v${version}`],
[/^You're up to date \(v(.+)\)\.$/, (_m, version) => `已是最新版本(v${version})。`],
[/^Update available: v(.+)$/, (_m, version) => `有可用更新:v${version}`],
[
/^Codeman updated to v([^:\s]+): (.+?)(?: \(\+(\d+) more\))?$/,
(_m, version, shown, more) => `Codeman 已更新到 v${version}:${shown}${more ? `(另有 ${more} 项)` : ''}`,
],
[/^Selected: (.+)$/, (_m, value) => `已选择:${value}`],
[/^Failed to (.+)$/, (_m, action) => `操作失败:${action}`],
[/^Will create: (.+)$/, (_m, path) => `将创建:${path}`],
+31
View File
@@ -1,6 +1,8 @@
import { describe, it, expect } from 'vitest';
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import vm from 'node:vm';
import { JSDOM } from 'jsdom';
// @ts-expect-error plain .mjs helper shared with scripts/generate-whats-new.mjs
import { extractHighlights, versionSection, buildWhatsNew } from '../scripts/lib/whats-new.mjs';
@@ -95,3 +97,32 @@ describe('shipped whats-new.json', () => {
);
});
});
describe('the announcement in zh-CN', () => {
const dom = new JSDOM('<!doctype html><html><body></body></html>', {
runScripts: 'outside-only',
url: 'http://localhost/',
});
vm.runInContext(readFileSync(resolve(root, 'src/web/public/i18n.js'), 'utf8'), dom.getInternalVMContext());
const api = (
dom.window as unknown as { CodemanI18n: { t(s: string): string; configure(o: Record<string, string>): void } }
).CodemanI18n;
api.configure({ language: 'zh-CN' });
it('translates the button and the toast frame, keeping the version and the English highlights', () => {
expect(api.t("See what's new")).toBe('查看更新内容');
expect(api.t('Codeman updated to v1.41.2: Tab layouts (#538) · Split view')).toBe(
'Codeman 已更新到 v1.41.2:Tab layouts (#538) · Split view'
);
expect(api.t('Codeman updated to v1.41.2: A · B · C (+5 more)')).toBe(
'Codeman 已更新到 v1.41.2:A · B · C(另有 5 项)'
);
});
it('builds the strings the pattern expects', () => {
const ui = readFileSync(resolve(root, 'src/web/public/settings-ui.js'), 'utf8');
expect(ui).toContain('`Codeman updated to v${runningVersion}: ${shown}${more}`');
expect(ui).toContain('` (+${notes.highlights.length - 3} more)`');
expect(ui).toContain(`label: "See what's new"`);
});
});