jackwener/maka-agent

[RFC] Define one i18n contract across Maka surfaces

开放

#2,672 创建于 2026年8月11日

 (0 条评论) (0 个反应) (0 位负责人)TypeScript (0 个派生)github user discovery
enhancementhelp wanted

仓库指标

星标
 (1 个星标)
PR 合并指标
 (PR 指标待抓取)

描述

Problem

Maka already has a sound i18n foundation:

  • UiLocale, UiLocalePreference, and locale resolution live in @maka/core
  • Renderer state flows through LocaleProvider
  • most UI domains use typed UiCatalog<T> catalogs
  • Astryx consumes the same resolved locale

The contract is not consistently applied across product surfaces.

Current gaps include:

  • plan-mode-panel.tsx contains Chinese-only user-facing copy
  • runtime-host-upgrade-dialog.ts contains English-only native-dialog copy
  • notification fallbacks are fixed to Chinese
  • the client-settings confirmation dialog is fixed to English
  • main-process surfaces variously use the persisted preference, the system locale, or a fixed language
  • error presentation is repeated across many files using raw error.message, Chinese-message detection, and separate English/Chinese classifiers
  • CLI and TUI have no locale authority and are effectively English-only
  • check-copy checks a few writing-style rules but does not detect untranslated user-facing copy

The physical distribution of copy is not itself the problem. Domain-owned catalogs are preferable to one global translation file. The problem is that locale ownership and presentation boundaries are not consistently defined or enforced.

Proposed direction

Keep the existing typed approach and make it the standard:

  1. One locale model

    Keep UiLocale, UiLocalePreference, system-language resolution, and Intl mapping in @maka/core.

  2. Domain-owned typed copy

    Each presentation domain owns a typed UiCatalog<T> next to its UI. Shared UI copy belongs to @maka/ui; Desktop-only and native copy belongs to Desktop.

    User-visible strings should not be embedded directly in component control flow or native-dialog construction.

  3. One Desktop locale authority

    Renderer and main-process surfaces should resolve the same persisted preference and system fallback. Native surfaces should receive or query this authority rather than independently choosing a language.

    Pre-settings startup failures may continue to use the system locale.

  4. Structured error presentation

    Runtime, protocol, and service layers should expose stable error codes and safe diagnostics. Presentation layers map those codes to localized copy.

    Raw message passthrough and “does this string contain Chinese?” checks should not be the localization mechanism.

  5. Explicit CLI/TUI policy

    Human-facing TUI and CLI help should use a small typed catalog based on the same supported locales. Locale selection should support an explicit override and an automatic system/environment fallback.

    Machine-readable output, protocol values, logs, JSONL, and exit semantics must remain locale-independent.

  6. A narrow enforcement check

    Extend repository checks to catch newly introduced user-visible literals in selected Renderer and native-dialog boundaries, with explicit exceptions where necessary.

    The check should prevent regressions without attempting to infer every string’s intent.

Initial migration scope

  • Plan Mode
  • Runtime Host upgrade dialogs
  • native notification fallbacks
  • client-settings confirmation
  • duplicated error-localization helpers
  • CLI help and the primary TUI chrome

Existing domain catalogs can migrate incrementally when touched. This should not become a repository-wide copy rewrite.

Non-goals

  • adopting i18next, ICU, or an external translation platform without a demonstrated need
  • moving all product copy into one global catalog
  • translating logs, protocol payloads, machine-readable output, user content, or model output
  • preserving raw backend error text as localized product copy
  • completing every historical copy cleanup in one PR

Acceptance criteria

  • English mode no longer exposes known Chinese-only product surfaces, and Chinese mode no longer exposes known English-only native dialogs
  • Renderer and post-startup native surfaces follow the same resolved Desktop locale
  • migrated error paths localize stable error codes without language-detection heuristics
  • TUI and human-facing CLI help have an explicit zh/en/automatic locale policy
  • machine-readable CLI and Runtime Host contracts remain unchanged
  • repository checks reject new hardcoded user-facing copy in the covered boundaries
  • the implementation retains typed domain catalogs and does not introduce a global translation framework

问题

Maka 已经具备合理的 i18n 基础:

  • UiLocaleUiLocalePreference 和语言解析位于 @maka/core
  • Renderer 通过 LocaleProvider 传递 locale
  • 大多数 UI 领域使用类型安全的 UiCatalog<T>
  • Astryx 使用同一个 resolved locale

但这套契约没有一致地覆盖所有产品界面。

目前可以确认的缺口包括:

  • plan-mode-panel.tsx 包含仅中文的用户文案
  • runtime-host-upgrade-dialog.ts 包含仅英文的 native dialog 文案
  • 系统通知 fallback 固定为中文
  • Client 设置修改确认框固定为英文
  • 不同 main-process surface 分别使用持久化偏好、系统语言或固定语言
  • 多处错误呈现分别使用原始 error.message、中文字符检测以及独立的中英文分类逻辑
  • CLI 和 TUI 没有 locale authority,目前实际上是 English-only
  • check-copy 只检查少量文案风格规则,不能发现未本地化的用户文案

Copy 文件分布在不同领域本身不是问题。由领域拥有 catalog 比单一全局翻译文件更合理。真正的问题是 locale ownership 和 presentation boundary 没有被一致定义和约束。

建议方向

保留现有的类型化方案,并将其确立为统一标准:

  1. 统一 locale model

    继续由 @maka/core 定义 UiLocaleUiLocalePreference、系统语言解析和 Intl 映射。

  2. 领域拥有类型安全的 copy

    每个 presentation domain 在自身 UI 附近拥有 typed UiCatalog<T>。共享 UI 文案属于 @maka/ui,Desktop 和 native 专属文案属于 Desktop。

    用户可见文本不应直接写在组件控制流或 native dialog 构造逻辑中。

  3. 统一 Desktop locale authority

    Renderer 和 main-process surface 应使用相同的持久化偏好及系统 fallback。Native surface 应接收或查询该 authority,而不是各自决定语言。

    在设置系统可用前发生的启动错误可以继续使用系统语言。

  4. 结构化错误呈现

    Runtime、protocol 和 service 层应提供稳定错误码及安全诊断;presentation 层负责将错误码映射为本地化文案。

    不再把原始消息透传或“字符串是否包含中文”作为本地化机制。

  5. 明确 CLI/TUI 策略

    面向人的 TUI 和 CLI help 使用一个复用相同 supported locales 的小型 typed catalog。Locale selection 支持显式 override,并支持基于系统或环境的自动选择。

    Machine-readable output、protocol value、日志、JSONL 和退出语义必须保持语言无关。

  6. 范围克制的约束检查

    扩展仓库检查,阻止在选定的 Renderer 和 native-dialog boundary 中新增用户可见字符串,并允许必要的显式例外。

    检查只用于阻止明显回归,不尝试推断所有字符串的用途。

首批迁移范围

  • Plan Mode
  • Runtime Host 升级对话框
  • Native notification fallback
  • Client 设置修改确认框
  • 重复的错误本地化 helper
  • CLI help 和主要 TUI chrome

其他已有领域 catalog 可以在后续修改时逐步迁移,不进行全仓文案重写。

非目标

  • 在没有明确需求时引入 i18next、ICU 或外部翻译平台
  • 将所有产品文案移入一个全局 catalog
  • 翻译日志、协议 payload、机器可读输出、用户内容或模型输出
  • 将原始 backend error text 作为本地化产品文案
  • 在一个 PR 中完成所有历史文案清理

验收标准

  • 英文模式不再显示已知的中文专属界面,中文模式不再显示已知的英文专属 native dialog
  • Renderer 和启动后的 native surface 使用同一个 resolved Desktop locale
  • 已迁移的错误路径通过稳定错误码完成本地化,不再依赖语言检测
  • TUI 和面向人的 CLI help 具有明确的 zhen 和自动语言策略
  • Machine-readable CLI 与 Runtime Host contract 保持不变
  • 仓库检查能够拒绝 covered boundary 中新增的硬编码用户文案
  • 实现继续使用 typed domain catalog,不引入全局翻译框架

贡献者指南