Fix Chinese i18n workbench controls

This commit is contained in:
Codex
2026-05-20 17:18:23 +08:00
parent 1c7ad37518
commit ffade3bad7
7 changed files with 44 additions and 7 deletions
+1
View File
@@ -804,6 +804,7 @@ Automation execution-layer PXX remains closed and its known scope stays frozen.
- First real Trader Mode R2 use loop executed on 2026-05-20: used remote `/trader-mode` as the primary screen, observed `Observe Only: Watch Candidate #4610: FVG retrace`, and recorded a real `No Trade` action from the UI because Candidate `4610` remained `blocked` / `executable=false`. This correctly updated `shadow_paper_observations` instead of creating a fake paper ticket: `operator_feedback_count` increased from `1` to `2`, `shadow_observation_count` increased from `14` to `15`, while `paper_ticket_count=0` and `paper_execution_count=0` stayed unchanged. Saved after-close draft note `operator_notes.id=3` with scope `weekly_review_draft`; `/trading/journal/generate` returned `created=0`, so `weekly_review_entry_count` remains `0` until a real execution-derived journal entry exists. Evidence screenshot saved at `output/playwright/trader-mode-r2-real-use-loop-390x844.png`. Current R2 gate remains `paper_ticket_sample_gate`; do not mark R2 completed. - First real Trader Mode R2 use loop executed on 2026-05-20: used remote `/trader-mode` as the primary screen, observed `Observe Only: Watch Candidate #4610: FVG retrace`, and recorded a real `No Trade` action from the UI because Candidate `4610` remained `blocked` / `executable=false`. This correctly updated `shadow_paper_observations` instead of creating a fake paper ticket: `operator_feedback_count` increased from `1` to `2`, `shadow_observation_count` increased from `14` to `15`, while `paper_ticket_count=0` and `paper_execution_count=0` stayed unchanged. Saved after-close draft note `operator_notes.id=3` with scope `weekly_review_draft`; `/trading/journal/generate` returned `created=0`, so `weekly_review_entry_count` remains `0` until a real execution-derived journal entry exists. Evidence screenshot saved at `output/playwright/trader-mode-r2-real-use-loop-390x844.png`. Current R2 gate remains `paper_ticket_sample_gate`; do not mark R2 completed.
- Trader Mode unified shell closure passed on 2026-05-20: `/trader-mode` now resolves to the same left-menu/right-workspace `index.html` shell instead of the standalone page, with the Trader Mode section active from the route and the sidebar `Trader Mode` tree item selected. The embedded Trader Mode surface keeps the fast-read status, live readout, fast queue, freshness, focus, action buttons, after-close draft, R2 evidence, and read-only boundary controls, while the generic workbench filter bar is hidden only for this section. `trader_mode.js` is scoped so it can run inside the workbench without leaking globals into `app.js`; keyboard shortcuts and auto-refresh are active only while the Trader Mode section is visible. Remote validation passed deploy smoke over 11 endpoints, gstack browser checks on `http://192.168.3.90:8000/trader-mode` (`bodySection=trader-mode`, active nav=`Trader Mode`, sidebar present, generic controls hidden, loaded status=`Observe Only`), `run_readonly_live_analysis_smoke.py`, and `run_remote_ops_smoke.py`. Evidence screenshot saved at `output/playwright/trader-mode-unified-shell-1366x768-loaded.png`. No change was made to `execution_allowed`, `decision_support_ready`, `real_live_ready`, risk governor, trust bucket, or operator confirmation protocol. - Trader Mode unified shell closure passed on 2026-05-20: `/trader-mode` now resolves to the same left-menu/right-workspace `index.html` shell instead of the standalone page, with the Trader Mode section active from the route and the sidebar `Trader Mode` tree item selected. The embedded Trader Mode surface keeps the fast-read status, live readout, fast queue, freshness, focus, action buttons, after-close draft, R2 evidence, and read-only boundary controls, while the generic workbench filter bar is hidden only for this section. `trader_mode.js` is scoped so it can run inside the workbench without leaking globals into `app.js`; keyboard shortcuts and auto-refresh are active only while the Trader Mode section is visible. Remote validation passed deploy smoke over 11 endpoints, gstack browser checks on `http://192.168.3.90:8000/trader-mode` (`bodySection=trader-mode`, active nav=`Trader Mode`, sidebar present, generic controls hidden, loaded status=`Observe Only`), `run_readonly_live_analysis_smoke.py`, and `run_remote_ops_smoke.py`. Evidence screenshot saved at `output/playwright/trader-mode-unified-shell-1366x768-loaded.png`. No change was made to `execution_allowed`, `decision_support_ready`, `real_live_ready`, risk governor, trust bucket, or operator confirmation protocol.
- Frontend Chinese/English i18n closure passed on 2026-05-20: added shared `/static/i18n.js`, default locale `zh-CN`, persistent `ai_ict_locale_v1`, topbar language switchers on the workbench, standalone Trader Mode fallback page, and training page. `app.js`, `trader_mode.js`, and `training.js` now route dynamic `setText` output through the same translation layer, so both static shell labels and live Trader Mode status/readout labels can switch between Chinese and English without changing backend payloads. Mutation handling was hardened to avoid self-triggered translation loops during language changes. Remote validation confirmed default Chinese with no stored locale (`lang=zh-CN`, heading `AI ICT 交易工作台`, status `仅观察`, readout `为什么不交易`) and English switching (`lang=en`, heading `AI ICT Trading Workbench`, status `Observe Only`), with no browser console errors. Evidence screenshots saved at `output/playwright/i18n-trader-mode-zh-default-1366x768.png` and `output/playwright/i18n-trader-mode-en-1366x768.png`. Local validation passed i18n/app/trader/training JS syntax checks, focused static/read-only/operator tests, script static checks, full unit discovery (`789` tests), deploy smoke over 11 endpoints, `run_remote_ops_smoke.py`, and `run_readonly_live_analysis_smoke.py`. No change was made to `execution_allowed`, `decision_support_ready`, `real_live_ready`, risk governor, trust bucket, or operator confirmation protocol. - Frontend Chinese/English i18n closure passed on 2026-05-20: added shared `/static/i18n.js`, default locale `zh-CN`, persistent `ai_ict_locale_v1`, topbar language switchers on the workbench, standalone Trader Mode fallback page, and training page. `app.js`, `trader_mode.js`, and `training.js` now route dynamic `setText` output through the same translation layer, so both static shell labels and live Trader Mode status/readout labels can switch between Chinese and English without changing backend payloads. Mutation handling was hardened to avoid self-triggered translation loops during language changes. Remote validation confirmed default Chinese with no stored locale (`lang=zh-CN`, heading `AI ICT 交易工作台`, status `仅观察`, readout `为什么不交易`) and English switching (`lang=en`, heading `AI ICT Trading Workbench`, status `Observe Only`), with no browser console errors. Evidence screenshots saved at `output/playwright/i18n-trader-mode-zh-default-1366x768.png` and `output/playwright/i18n-trader-mode-en-1366x768.png`. Local validation passed i18n/app/trader/training JS syntax checks, focused static/read-only/operator tests, script static checks, full unit discovery (`789` tests), deploy smoke over 11 endpoints, `run_remote_ops_smoke.py`, and `run_readonly_live_analysis_smoke.py`. No change was made to `execution_allowed`, `decision_support_ready`, `real_live_ready`, risk governor, trust bucket, or operator confirmation protocol.
- Frontend i18n regression follow-up passed on 2026-05-20: fixed whitespace-preserving text-node translation so Chinese mode now translates top controls such as `Instrument ID`, `Timeframe`, `Limit`, `Auto Refresh`, `Execution Status`, `Session Focus`, `Trust Class`, and `Search` on `/trader-mode#overview`. The workbench active-section marker moved from `body[data-workbench-section]` to `body[data-active-workbench-section]` to avoid selector collisions with real content sections during browser automation and Trader Mode visibility checks. Added missing Chinese button labels for dynamic workbench actions including `Generate Active Plan`, `Run Watch`, `Risk Check`, `Cleanup Old Captures`, `Reconcile Real Trades`, `Cancel`, `Close`, `Sync`, note/review-packet buttons, and visual feedback buttons. Local validation passed `node --check src/web/app.js`, `node --check src/web/i18n.js`, 27 focused static/read-only/operator tests, secret static checks, script static checks, full unit discovery (`789` tests), and `git diff --check` with only LF/CRLF warnings. Live deploy completed with 11 deploy smoke endpoints; `run_remote_ops_smoke.py` and `run_readonly_live_analysis_smoke.py` passed, with `ready_for_readonly_live_analysis=true`, `must_not_trade=true`, and `submit_cancel_or_live_execution_called=false`. gstack browser automation cold-started `http://192.168.3.90:8000/trader-mode?verify=20260520b#overview`, confirmed `lang=zh-CN`, no old body selector collision, Chinese top controls, 17 left-menu pages navigable, no console errors, and clicked only safe `刷新` while skipping write/record/reconcile buttons to avoid polluting live state. Evidence screenshot saved at `output/playwright/i18n-overview-controls-zh-final-1366x768.png`. No change was made to `execution_allowed`, `decision_support_ready`, `real_live_ready`, risk governor, trust bucket, or operator confirmation protocol.
- Current assisted-analysis next gate: keep R1/R2 focused on `decision_support_ready` trust/sample/quality evidence and shadow/paper/operator feedback collection. OKX trade-permission sandbox smoke is deferred until the project explicitly re-enters execution adapter or real-trading preparation. - Current assisted-analysis next gate: keep R1/R2 focused on `decision_support_ready` trust/sample/quality evidence and shadow/paper/operator feedback collection. OKX trade-permission sandbox smoke is deferred until the project explicitly re-enters execution adapter or real-trading preparation.
## Exact Next Step ## Exact Next Step
+1
View File
@@ -921,6 +921,7 @@
- [x] P0-5 minimal operations loop: `/trader-mode` supports one-click daily observation, operator agreement/disagreement/no-trade/more-evidence, and quick notes without requiring paper ticket samples - [x] P0-5 minimal operations loop: `/trader-mode` supports one-click daily observation, operator agreement/disagreement/no-trade/more-evidence, and quick notes without requiring paper ticket samples
- [x] Trader Mode usefulness compression: first screen and watchlist now answer why not to trade, what to watch next, why the unique focus matters, whether data is stale, and what to wait for when there is no candidate; remote deploy, ops smoke, read-only live analysis smoke, and 390/1366 gstack screenshots passed - [x] Trader Mode usefulness compression: first screen and watchlist now answer why not to trade, what to watch next, why the unique focus matters, whether data is stale, and what to wait for when there is no candidate; remote deploy, ops smoke, read-only live analysis smoke, and 390/1366 gstack screenshots passed
- [x] First real Trader Mode R2 usage loop: recorded UI `No Trade` for blocked Candidate #4610, increased operator feedback from 1 to 2, saved after-close draft note, and verified paper ticket/execution/weekly journal counts were not fabricated - [x] First real Trader Mode R2 usage loop: recorded UI `No Trade` for blocked Candidate #4610, increased operator feedback from 1 to 2, saved after-close draft note, and verified paper ticket/execution/weekly journal counts were not fabricated
- [x] Frontend i18n regression follow-up: Chinese mode now translates whitespace-padded top controls on `/trader-mode#overview`, dynamic workbench buttons such as `Run Watch` / `Risk Check` / `Reconcile Real Trades`, and active-section automation no longer collides with body attributes; deploy smoke, remote ops smoke, read-only live smoke, and 17-page gstack browser click audit passed
- [ ] R2 paper-ticket sample gate is waiting on a real executable candidate; do not fabricate paper tickets from blocked candidates - [ ] R2 paper-ticket sample gate is waiting on a real executable candidate; do not fabricate paper tickets from blocked candidates
- [ ] R2 operator feedback sample gate still needs at least 3 more real feedback samples (`operator_feedback_count=2/5`) - [ ] R2 operator feedback sample gate still needs at least 3 more real feedback samples (`operator_feedback_count=2/5`)
- [ ] R2 weekly review visible gate still needs a real execution-derived journal/weekly review entry (`weekly_review_entry_count=0`) - [ ] R2 weekly review visible gate still needs a real execution-derived journal/weekly review entry (`weekly_review_entry_count=0`)
Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

+1 -1
View File
@@ -192,7 +192,7 @@ function activateWorkbenchSection(sectionId, options = {}) {
section.classList.toggle('is-active', isActive); section.classList.toggle('is-active', isActive);
section.toggleAttribute('hidden', !isActive); section.toggleAttribute('hidden', !isActive);
}); });
document.body.dataset.workbenchSection = activeId; document.body.dataset.activeWorkbenchSection = activeId;
workbenchNavButtons.forEach((button) => { workbenchNavButtons.forEach((button) => {
const isActive = button.dataset.workbenchTarget === activeId; const isActive = button.dataset.workbenchTarget === activeId;
button.classList.toggle('is-active', isActive); button.classList.toggle('is-active', isActive);
+29 -4
View File
@@ -37,6 +37,25 @@
'Trust Class': '信任分组', 'Trust Class': '信任分组',
'Search': '搜索', 'Search': '搜索',
'Refresh': '刷新', 'Refresh': '刷新',
'Generate Active Plan': '生成当前计划',
'Run Watch': '运行观察',
'Run Observe': '运行观察',
'Run Confirm Check': '运行确认检查',
'Risk Check': '风险检查',
'Confirm': '确认',
'Paper Execute': '纸面执行',
'Semi-Auto Submit': '半自动提交',
'Reconcile Real Trades': '对账真实成交',
'Cleanup Old Captures': '清理旧截图',
'Generate Journal': '生成日志',
'Generate Review Packet': '生成复核包',
'Generate Journal Backfill': '生成日志回填',
'Save Note': '保存备注',
'Prefill Focus Note': '预填焦点备注',
'Useful': '有用',
'Misleading': '误导',
'Actionable': '可执行',
'Capture Feedback': '记录反馈',
'All': '全部', 'All': '全部',
'All Sessions': '全部时段', 'All Sessions': '全部时段',
'Whitelist': '白名单', 'Whitelist': '白名单',
@@ -47,6 +66,9 @@
'Pending': '待处理', 'Pending': '待处理',
'Rejected': '已拒绝', 'Rejected': '已拒绝',
'Cancelled': '已取消', 'Cancelled': '已取消',
'Cancel': '取消',
'Close': '关闭',
'Sync': '同步',
'Filters: none': '筛选:无', 'Filters: none': '筛选:无',
'Loading workspace...': '正在加载工作台...', 'Loading workspace...': '正在加载工作台...',
'Loading Trader Mode...': '正在加载交易员模式...', 'Loading Trader Mode...': '正在加载交易员模式...',
@@ -238,12 +260,15 @@
function translateText(value, locale = currentLocale) { function translateText(value, locale = currentLocale) {
const source = value == null ? '' : String(value); const source = value == null ? '' : String(value);
if (locale === 'en' || !source.trim()) return source; if (locale === 'en' || !source.trim()) return source;
const exact = zhExact[source.trim()]; const leading = source.match(/^\s*/)?.[0] || '';
if (exact && source.trim() === source) return exact; const trailing = source.match(/\s*$/)?.[0] || '';
const core = source.slice(leading.length, source.length - trailing.length);
const exact = zhExact[core];
if (exact) return `${leading}${exact}${trailing}`;
for (const [pattern, replacement] of zhPatterns) { for (const [pattern, replacement] of zhPatterns) {
if (pattern.test(source)) return applyPhraseTranslations(source.replace(pattern, replacement)); if (pattern.test(core)) return `${leading}${applyPhraseTranslations(core.replace(pattern, replacement))}${trailing}`;
} }
return applyPhraseTranslations(source); return `${leading}${applyPhraseTranslations(core)}${trailing}`;
} }
function setDocumentLanguage() { function setDocumentLanguage() {
+2 -2
View File
@@ -176,8 +176,8 @@ body {
.workbench-content { .workbench-content {
min-width: 0; min-width: 0;
} }
body[data-workbench-section="trader-mode"] #workbenchContent > .controls, body[data-active-workbench-section="trader-mode"] #workbenchContent > .controls,
body[data-workbench-section="trader-mode"] #workbenchContent > .filters-bar { body[data-active-workbench-section="trader-mode"] #workbenchContent > .filters-bar {
display: none; display: none;
} }
.workbench-content .controls, .workbench-content .controls,
+10
View File
@@ -157,6 +157,7 @@ class ApiStaticServerTests(unittest.TestCase):
"initializeWorkbenchNavigation", "initializeWorkbenchNavigation",
"getPathWorkbenchSection", "getPathWorkbenchSection",
"workbench-section-change", "workbench-section-change",
"activeWorkbenchSection",
"aiIctActiveWorkbenchSection", "aiIctActiveWorkbenchSection",
"request_timeout", "request_timeout",
"AbortController", "AbortController",
@@ -167,6 +168,7 @@ class ApiStaticServerTests(unittest.TestCase):
".workbench-sidebar", ".workbench-sidebar",
".workbench-nav button.is-active", ".workbench-nav button.is-active",
".workspace-section.is-active", ".workspace-section.is-active",
"data-active-workbench-section",
".language-switcher", ".language-switcher",
): ):
self.assertIn(expected, styles_css) self.assertIn(expected, styles_css)
@@ -188,8 +190,16 @@ class ApiStaticServerTests(unittest.TestCase):
"仅观察", "仅观察",
"不要使用", "不要使用",
"只读实盘分析", "只读实盘分析",
"Generate Active Plan",
"Run Watch",
"Reconcile Real Trades",
"Cleanup Old Captures",
"'Cancel':",
"'Sync':",
"ai_ict_locale_v1", "ai_ict_locale_v1",
"ai-ict-locale-change", "ai-ict-locale-change",
"const core = source.slice(leading.length",
"zhExact[core]",
): ):
self.assertIn(expected, i18n_js) self.assertIn(expected, i18n_js)