feat(achievements): add i18n support with Chinese (zh-CN) translations - #23476
feat(achievements): add i18n support with Chinese (zh-CN) translations#23476kaiwer1 wants to merge 4 commits into
Conversation
Add locale-based internationalization to the achievements plugin: - New locales/zh-CN.json with 信达雅 translations for 60 achievements, 5 tier names, ~30 metric labels, and common UI strings - plugin_api.py: detect Accept-Language header and apply translations at the routing layer, keeping the cache layer in English - Backward compatible: English requests hit the original code path with zero overhead, zh-CN requests apply translation overlay - Fix unrelated bug: return clean -> return _build_pending_snapshot(now) (was referencing undefined variable at line ~1113) Architecture: translations stored in JSON files under locales/, new languages can be added without modifying plugin_api.py.
…tx() - Add _uiData module variable to store backend _ui translations - Add PATH_TO_UI mapping table (all tx() paths -> flat _ui keys) - Patch tx() to prioritize _uiData, fallback to SDK i18n, then en - AchievementsPage.load()/refresh() save _uiData on API response - Fixes PR conflict resolution that lost all client i18n code
teknium1
left a comment
There was a problem hiding this comment.
Thanks for carrying the dynamic achievement-content translation work forward. The remaining premise is valid: current main localizes static achievement UI through web/src/i18n/zh.ts:491, but the plugin still renders API-provided names, categories, descriptions, and criteria verbatim at plugins/hermes-achievements/dashboard/dist/index.js:523-542.
Problems
- The PR replaces the request helper with direct
fetchatplugins/hermes-achievements/dashboard/dist/index.js:164(right side). Current main requiresSDK.fetchJSONfor both loopback token and gated-OAuth-cookie authentication; its inline contract says manual fetching returns 401 in gated mode atplugins/hermes-achievements/dashboard/dist/index.js:51-60. - The route-level localization changes have no regression coverage. Existing integration tests in
tests/plugins/test_achievements_plugin.pycover scanning and cache behavior, not locale headers or localized endpoint payloads.
Suggested changes
- Preserve
SDK.fetchJSONand pass the locale header through its options. - Keep shared
web/src/i18nfor static chrome and restrict the overlay to dynamic achievement data. - Add English-fallback and zh-CN route tests, including stable CSS/state identifiers.
Automated hermes-sweeper review.
| // Forward the plugin's locale to the backend so achievement names, | ||
| // descriptions, criteria, and tier labels are translated server-side. | ||
| if (_pluginLocale && _pluginLocale !== "en" && !headers.has("Accept-Language")) { | ||
| headers.set("Accept-Language", _pluginLocale); |
There was a problem hiding this comment.
Please keep SDK.fetchJSON as the transport and pass the locale header through its options. Current main documents at this helper that manual fetch with window.__HERMES_SESSION_TOKEN__ 401s in gated OAuth mode because it omits the cookie-based authentication path.
GottZ
left a comment
There was a problem hiding this comment.
This was generated by AI during triage.
Summary
Three PRs address Chinese localization for the achievements plugin: #18747 and #22595 implemented overlapping static UI translations and were superseded by merged #22914, while #23476 targets the remaining API-provided achievement names, descriptions, and criteria. #23476 does not actually localize API-provided categories because _apply_locale() copies only name and description, and it currently introduces authentication and English-output regressions.
Related pull requests
- #18747 [closed]
duplicate— (+354/-48) — superseded reference: Added inline zh-CN UI translations plus backend-generated Chinese names, descriptions, categories, and criteria. It remains relevant as a reference implementation, but contributor review confirms it was superseded by merged #22914, which incorporated its translation work into broader 16-language coverage. - #22595 [closed]
related— (+1023/-259) — superseded reference: Moved achievements static UI strings into shared typed web i18n catalogs and also carried unrelated Kanban localization changes. It remains relevant for its shared-i18n approach, but contributor review confirms it was superseded by merged #22914 and should not be reopened. - #23476
related— (+752/-31) — keep open, not merge-ready: Adds locale JSON and server-side localization for API-provided achievement names, descriptions, and criteria, but not categories despite category translations being present. This aligns with the keep_open review on #23476, whose blockers remain: the diff replacesSDK.fetchJSONwith directfetch, breaking gated OAuth-cookie authentication; adds no locale endpoint regression tests; and regresses English threshold criteria by emitting Chinese punctuation/text (。等级阶梯) on the English path.
Duplicates
#18747 and the achievements portion of #22595 substantially overlap on Chinese static achievements UI localization and were both superseded by merged #22914; #23476 is not a full duplicate because it addresses the still-untranslated dynamic API content.
Suggested consolidation
Keep #23476 open as the consolidation target, but do not merge it yet. Preserve SDK.fetchJSON while forwarding Accept-Language, add endpoint-level locale and English-fallback tests, restore fully English punctuation and wording in English criteria, and either implement category localization consistently or remove that claim; #18747 and #22595 should remain closed as superseded by #22914.
Complex graph
flowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
subgraph Dup18747 ["PRs duplicating each other"]
P18747["PR #18747 (closed)"]
P22595["PR #22595 (closed)"]
P23476["PR #23476 (open)"]
end
class P18747 closed
class P22595 closed
class P23476 open
class P23476 target
click P18747 "https://github.com/NousResearch/hermes-agent/pull/18747"
click P22595 "https://github.com/NousResearch/hermes-agent/pull/22595"
click P23476 "https://github.com/NousResearch/hermes-agent/pull/23476"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed or no verify verdict yet (state tag in the node label).
Cross-PR triage: Reviewed 3 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 200 kB of PR diffs, 4 kB of issue/PR text, 3 kB of discussion (3 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.
Summary
Add full internationalization (i18n) support to the Hermes Achievements plugin. Includes:
_t(key, fallback)helper renders translated labels on cards, filters, tier legend, stats, and share buttonsTesting
_uifield when en-US)