From ed4d640c1dfbef1078e8458a670e0901b16c49b1 Mon Sep 17 00:00:00 2001 From: Willi Budzinski Date: Sat, 20 Jun 2026 03:56:24 +0200 Subject: [PATCH 1/5] fix(viewer): make Chinese locale selectable --- .env.example | 1 + README.md | 2 + .../arena-synthesis.md | 49 ++++ .../plan.md | 249 ++++++++++++++++++ .../todo.md | 158 +++++++++++ src/viewer/index.html | 201 ++++++++++---- src/viewer/locales.ts | 8 + src/viewer/locales/en.json | 83 +++++- src/viewer/locales/zh.json | 83 +++++- test/viewer-i18n.test.ts | 86 ++++++ 10 files changed, 870 insertions(+), 50 deletions(-) create mode 100644 docs/todos/2026-06-19-issue-288-web-display-issue/arena-synthesis.md create mode 100644 docs/todos/2026-06-19-issue-288-web-display-issue/plan.md create mode 100644 docs/todos/2026-06-19-issue-288-web-display-issue/todo.md diff --git a/.env.example b/.env.example index 9e4c7c8a9..c1b5ed31f 100644 --- a/.env.example +++ b/.env.example @@ -191,6 +191,7 @@ # AGENTMEMORY_IMPORT_TIMEOUT_MS=120000 # import-jsonl POST timeout # AGENTMEMORY_URL=http://localhost:3111 # REST base URL — honored by status, doctor, MCP shim # AGENTMEMORY_VIEWER_URL=http://localhost:3113 # Override the viewer URL printed by `agentmemory status` +# VIEWER_LANGUAGE=zh-CN # Startup default for the viewer UI; users can switch in the viewer header # AGENTMEMORY_EXPORT_ROOT=~/agentmemory-backup # Default destination for `agentmemory export` # AGENTMEMORY_BACKUP_ENABLED=true # Periodically write logical JSON exports # AGENTMEMORY_BACKUP_DIR=~/.agentmemory/backups # Required when scheduled backups are enabled diff --git a/README.md b/README.md index d0572b8b5..ff88d89a2 100644 --- a/README.md +++ b/README.md @@ -1248,6 +1248,8 @@ Auto-starts on port `3113`. Live observation stream, session explorer, memory br open http://localhost:3113 ``` +The viewer ships English and Simplified Chinese UI strings. It auto-selects Chinese for Chinese browser language preferences when no local viewer preference has been saved, and the header language selector persists your choice in the browser. Operators can also set the startup default with `VIEWER_LANGUAGE=zh` or `VIEWER_LANGUAGE=zh-CN`. + The viewer server binds to `127.0.0.1` by default. The REST-served `/agentmemory/viewer` endpoint follows the normal `AGENTMEMORY_SECRET` bearer-token rules. CSP headers use a per-response script nonce and disable inline handler attributes (`script-src-attr 'none'`). --- diff --git a/docs/todos/2026-06-19-issue-288-web-display-issue/arena-synthesis.md b/docs/todos/2026-06-19-issue-288-web-display-issue/arena-synthesis.md new file mode 100644 index 000000000..3d1fec326 --- /dev/null +++ b/docs/todos/2026-06-19-issue-288-web-display-issue/arena-synthesis.md @@ -0,0 +1,49 @@ +# Issue 288 Arena Synthesis + +Artifact: issue-validity and fix-direction decision for GitHub issue #288. + +Rubric: +- Issue evidence accuracy. +- Current-code reproduction clarity. +- Duplicate/staleness diligence. +- Scoped fix direction. +- Verification specificity. + +## Candidate Scores + +| Candidate | Score | Summary | +| --- | ---: | --- | +| A | 23/25 | Correctly identified partial existing Chinese locale support and remaining coverage gaps; strongest route/build inventory. | +| B | 25/25 | Clearest conclusion: valid unresolved coverage/discoverability gap, not fixed, with practical implementation direction. | +| C | 21/25 | Strong rendered-output proof and font/search nuance, but verification attempt caused ignored dependency artifacts. | + +## Pick + +Base: Candidate B. + +Reason: Candidate B best distinguishes existing i18n foundation from the unresolved user-facing gap. It recommends a scoped fix that does not require API, auth, schema, dependency, or architecture changes. + +## Grafts + +- From Candidate A: keep the route/build inventory in scope and remember that the shipped legacy viewer remains the production surface while the Vue/Vite app is preview-only. +- From Candidate A: do not import upstream PR #673 wholesale; local history already adapted the safe foundation. +- From Candidate C: use rendered-output style checks where practical so tests prove Chinese surfaces are reachable, not just locale files exist. +- From Candidate C: CJK search is separate from UI localization and must not be treated as closing this issue. +- From Candidate C: font fallback can improve Chinese readability, but font-only work does not satisfy the issue by itself. + +## Rejections + +- Close as already fixed: rejected because major shipped viewer surfaces remain hardcoded English and `VIEWER_LANGUAGE` is not discoverable for ordinary users. +- Close as duplicate without implementation: rejected because the current request requires a Human Checkpoint for duplicate closure and the arena found valid unresolved scope. +- Replace the viewer architecture: rejected because issue #148 owns the Vue/Vite migration and the shipped viewer remains `src/viewer/index.html`. +- Add runtime machine translation or external services: rejected because checked-in locale strings are safer and avoid privacy/CSP/network consequences. + +## Decision + +Proceed with a scoped valid-issue implementation: +- expose bundled locales to the browser safely; +- add a visible language selector with local persistence and Chinese-browser preference handling; +- expand Chinese locale keys for representative Dashboard and Memories surfaces; +- document `VIEWER_LANGUAGE=zh` / `zh-CN` and the in-viewer picker. + +Verification must preserve existing CSP/nonced-script behavior, translated-attribute allowlist restrictions, viewer layout, and package build behavior. diff --git a/docs/todos/2026-06-19-issue-288-web-display-issue/plan.md b/docs/todos/2026-06-19-issue-288-web-display-issue/plan.md new file mode 100644 index 000000000..97ed53ddb --- /dev/null +++ b/docs/todos/2026-06-19-issue-288-web-display-issue/plan.md @@ -0,0 +1,249 @@ +# Issue 288 Viewer Chinese Localization Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make the shipped viewer's Chinese localization directly selectable and more complete on high-traffic Dashboard and Memories surfaces. + +**Architecture:** Keep the existing nonced locale injection and static legacy viewer. Extend the injected locale bundle with bundled `available` locale data, add client-side locale selection/localStorage/browser-language resolution, and route representative Dashboard/Memories strings through existing safe translation helpers. + +**Tech Stack:** TypeScript, static HTML/JavaScript viewer, JSON locale files, Vitest, pnpm. + +--- + +## Files + +- Modify: `src/viewer/locales.ts` +- Modify: `src/viewer/index.html` +- Modify: `src/viewer/locales/en.json` +- Modify: `src/viewer/locales/zh.json` +- Modify: `test/viewer-i18n.test.ts` +- Modify: `test/viewer-security.test.ts` +- Modify: `README.md` +- Modify: `.env.example` +- Modify: `docs/todos/2026-06-19-issue-288-web-display-issue/todo.md` + +## Task 1: Red Tests For Switchable Viewer Locales + +- [x] **Step 1: Add failing bundle and document tests** + +Add tests to `test/viewer-i18n.test.ts` that assert: +- `buildLocaleBundle("en")` exposes `available.en` and `available.zh`. +- the rendered document includes `id="language-select"`. +- the rendered document includes the `agentmemory-viewer-language` storage key and `navigator.languages` browser-language check. +- `zh.json` contains representative Dashboard and Memories keys such as `dashboard.first_run_eyebrow`, `dashboard.cards.sessions`, `memories.search_placeholder`, and `common.delete`. +- the viewer source routes representative Dashboard and Memories HTML-builder strings through escaped `t(...)`: first-run copy, stat labels, Memories search/empty states/table headers, and delete modal copy. +- a viewer sandbox test can render Dashboard/Memories in English, switch to Chinese, and observe representative dynamic text change without a reload. + +- [x] **Step 2: Verify red** + +Run: + +```bash +corepack pnpm exec vitest run test/viewer-i18n.test.ts -t "viewer locale" +``` + +Expected: fail because `available`, the picker, and new keys do not exist. + +Evidence: failed 4 expected tests after deterministic pnpm setup. + +## Task 2: Expose Locale Data Safely + +- [x] **Step 1: Extend `LocaleBundle`** + +Update `src/viewer/locales.ts` so `LocaleBundle` includes: + +```ts +available: Record; +``` + +Build it from checked-in `en` and `zh` locale files only. Keep the existing `lang`, `messages`, and `fallback` fields for compatibility. + +- [x] **Step 2: Verify green for bundle tests** + +Run: + +```bash +corepack pnpm exec vitest run test/viewer-i18n.test.ts -t "bundle" +``` + +Expected: pass for the bundle tests that do not depend on HTML picker code yet. + +Evidence: full focused i18n suite passed after implementation. + +## Task 3: Add Viewer Language Picker Runtime + +- [x] **Step 1: Add picker markup and runtime selection** + +Modify `src/viewer/index.html`: +- Add a compact ` + + + live updates off @@ -1141,7 +1161,11 @@

agentmemory