mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 09:19:42 +02:00
fix(i18n): zh-CN for the case picker rows, Bottom bar settings, new toasts, tile and spreadsheet text
- Case picker: the "New or link a case…" and "Case settings…" rows that replaced the translated + and gear buttons get zh-CN entries reusing the buttons' wording, plus the list's "No cases match". - App Settings, Bottom bar: the whole group translates as one (heading, the four Git status rows with #543's max repositories and git timeout, and their descriptions), so it never reads half English. The Git panel's two button names, which the new "Git status" key reaches, read naturally too. - Toasts: the three "Could not open a new window for this ..." errors and the dictation-closed warning. - Spreadsheet preview: "Spreadsheet preview failed (<status>)" gets a pattern. Worker refusals map their error code to one user sentence each in the renderer (the raw message goes to the console), feature ids read as words (pivot tables, external links), and the notice bar translates each item before the join; a number format's code passes through untouched. The worker and core are unchanged, so their pinned strings and the asset version hash stay as they were. - Header Stats Style Tiles: the connection tile's value word reads in Chinese through scoped "Connection tile: <word>" keys, never bare-word keys ("retry" is also the orchestrator's Retry button, "LIVE" a resume list badge). The indicator cache now includes the UI language, so a language switch repaints it on the next update. - Tile grid: the "Loading…" label was CSS content text the translator cannot reach; it is now content: attr(data-loading-label), written through the translator when the tile is built and each time it starts loading. Tests pin every new string (zh differs, no English left, English unchanged) and fail without these changes: the tile harvest sees the loading label and the rename field, a CSS guard keeps words out of tile generated content, the Bottom bar group, the case picker rows and toasts read from their source, the connection tile across a language switch, and the spreadsheet error codes, notice bar and status line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,9 @@
|
||||
* - The parts only the new styles draw (stat rings, plan rings, meters, tile words)
|
||||
* are rendered with sane values and hidden by default in CSS, which is what
|
||||
* keeps 'classic' looking exactly as before.
|
||||
* - The connection tile's value word reads in Chinese through i18n.js's real
|
||||
* t(), from scoped keys (a bare 'retry' or 'live' key would also translate
|
||||
* other surfaces), and follows a language switch.
|
||||
*
|
||||
* The real modules run INSIDE a JSDOM window (runScripts: 'outside-only').
|
||||
*
|
||||
@@ -22,6 +25,7 @@
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import vm from 'node:vm';
|
||||
import { JSDOM } from 'jsdom';
|
||||
import postcss from 'postcss';
|
||||
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||
@@ -195,6 +199,62 @@ describe('the parts the new styles draw', () => {
|
||||
expect(document.getElementById('connectionTileValue')!.className).toBe('connection-tile-value connected');
|
||||
});
|
||||
|
||||
it('writes the value word in the UI language, from scoped keys, and follows a language switch', () => {
|
||||
const translator = (language: string) => {
|
||||
const dom = new JSDOM('<!doctype html><html><body></body></html>', {
|
||||
runScripts: 'outside-only',
|
||||
url: 'http://localhost/',
|
||||
});
|
||||
vm.runInContext(read('i18n.js'), dom.getInternalVMContext(), { filename: 'i18n.js' });
|
||||
const api = (dom.window as unknown as { CodemanI18n: { t(s: string): string; configure(o: object): void } })
|
||||
.CodemanI18n;
|
||||
api.configure({ language });
|
||||
return { t: api.t, close: () => dom.window.close() };
|
||||
};
|
||||
const zh = translator('zh-CN');
|
||||
const en = translator('en');
|
||||
try {
|
||||
window.codemanT = zh.t;
|
||||
window.CodemanI18n = { language: 'zh-CN' };
|
||||
const app = makeApp();
|
||||
app._computeConnectionDescriptor = () => ({
|
||||
display: 'flex',
|
||||
dotClass: 'connection-dot connected',
|
||||
text: 'WS',
|
||||
title: 'Terminal connected over WebSocket',
|
||||
});
|
||||
app._updateConnectionIndicator();
|
||||
expect(document.getElementById('connectionTileLabel')!.textContent).toBe('WS');
|
||||
expect(document.getElementById('connectionTileValue')!.textContent).toBe('已连接');
|
||||
// The same descriptor after a switch back to English is not skipped as unchanged.
|
||||
window.codemanT = en.t;
|
||||
window.CodemanI18n = { language: 'en' };
|
||||
app._updateConnectionIndicator();
|
||||
expect(document.getElementById('connectionTileValue')!.textContent).toBe('live');
|
||||
|
||||
// Every value word has its own Chinese, and none is a bare key.
|
||||
window.codemanT = zh.t;
|
||||
const values = [
|
||||
'connection-dot connected',
|
||||
'connection-dot fallback',
|
||||
'connection-dot offline',
|
||||
'connection-dot draining',
|
||||
'connection-dot reconnecting',
|
||||
].map((dotClass) => app._connectionTileWords({ dotClass, text: '' }).value);
|
||||
expect(values).toEqual(['live', 'fallback', 'offline', 'queued', 'retry']);
|
||||
const shown = values.map((value: string) => app._connectionTileValueText(value));
|
||||
expect(shown.filter((text: string) => /[A-Za-z]/.test(text))).toEqual([]);
|
||||
expect(values.filter((value: string) => zh.t(value) !== value)).toEqual([]);
|
||||
// The span the observer must leave alone (its text is set here, already translated).
|
||||
expect(INDEX).toMatch(/id="connectionTileValue" data-i18n-skip>/);
|
||||
} finally {
|
||||
delete window.codemanT;
|
||||
delete window.CodemanI18n;
|
||||
zh.close();
|
||||
en.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('fills the CPU and MEM rings from the stats poll, clamped, red past 80%', () => {
|
||||
const app = makeApp();
|
||||
const ring = (id: string) => {
|
||||
|
||||
Reference in New Issue
Block a user