omp packages

pi-localize1.1.0

Localize pi's interface — command descriptions and panel descriptions — and generate language packs on demand with /localize.

amber__xxx Published 1 month ago MIT ~331 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

pi-localize

/localize 语言选择器

把 pi 界面的英文换成你的语言。只做两件事:

  1. / 命令背后的那行描述(含参数补全里的描述);
  2. 设置 / 选择器 / 子菜单里,条目标题下方的描述(含第三方命令与插件)。

语言包不随包发布:你选一次语言,pi 用你自己的 agent、在你自己的机器上生成它。没有运行时翻译, 除了你那次模型调用发送的内容以外,什么都不外发。

覆盖范围

钩子 翻译什么 永不触碰
ctx.ui.addAutocompleteProvider / 命令描述、参数补全描述 命令名(label)、文件补全
活的组件树 + 实例 render 面板 / 选择器 / 子菜单条目的 description label、values、currentValue、聊天正文、页脚

对话框标题、空状态、状态标签、键位提示行暂不翻译:它们属于规划中的类别,加类别不需要动运行时骨架 (见 docs/adr/0001-scope-and-categories.md)。

需求

  • 支持扩展的 pi(只用文档化钩子:addAutocompleteProvider、registerCommand、getCommands)。
  • Node 20+。
  • @earendil-works/pi-tui —— 由 pi 在运行时提供,所以只声明为 peer dependency,绝不打包。
  • 可选:pi-subagents(或任何注册 subagents / run 命令的扩展)。装了它,生成本语言包会切成并行批次。

安装

pi install npm:pi-localize                        # 从 npm
pi install git:github.com/JBP-1994/pi-localize    # 从 git
pi install /absolute/path/to/pi-localize          # 从本地 checkout

装完 /reload 或重启 pi,然后跑 /localize。

使用

/localize

用 ↑ / ↓ 选语言,Enter 确认,Esc 退出。每一行都写清了会发生什么:英文是「源语言 —— 无需翻译」, 没有语言包的是「还没有语言包 —— 选中即开始生成」。

状态 结果
该语言还没有包 agent 生成一个:lang/<code>.mjs 加 lang/ui/<code>.mjs,写好 localize.config.json,下一轮生效,不用重启。
已有语言包 二选一:启用当前的(直接用) 或 全量重建。

首次生成的成本:这是一次真实的模型调用,花你自己的额度。按当前 pi 界面 + 已装插件,大概要翻几百条文案。

pi 或插件更新后,再跑 /localize → 全量重建:每次都把整包重译一遍 —— 不读旧包、不复用旧译文 (见 docs/adr/0006-full-rebuild-every-time.md)。记忆会让一个包里同时存在两套措辞,而模型漏抄一条就 静默丢一条。代价是每次都要翻整包:本机 344 条约 9 批子代理、几分钟。

配置

项 位置
当前语言 包目录下的 localize.config.json:{ "locale": "ja" }。默认 en,即不翻译。
换个配置位置 PI_LOCALIZE_CONFIG=/path/to/localize.config.json
命令快照(供 scan / check 用) 系统临时目录的 pi-localize-commands.json;PI_LOCALIZE_COMMANDS 可覆盖。

改配置在 session_start 时生效,所以 /reload 就够,不用重启。

语言

可选语言表在 lang/languages.mjs,只收 9 门常用语言(判据见 ADR 0005)。英文的地区变体故意不收:它们会和源语言完全一样。

表外的语言仍可选:选择器最后一行「输入其他语言」接受任意 BCP-47 代码,名称与旗帜由 Intl 现算。

加一门语言:在 lang/languages.mjs 加一行(code、旗帜、名称),然后跑 /localize 选它。

贡献语言包:语言包默认 gitignore。要贡献:

git add -f lang/<code>.mjs lang/ui/<code>.mjs   # 越过 .gitignore
npm test                                        # 结构、占位符、术语
npm run test:guards                             # 每条键都能重新生成,且没有行标题混入

语言包怎么生成

三条渠道的候选合成一个提示词,agent 只翻译、不判断。候选永远是整包(没有翻译记忆,见 ADR 0006),扩展自己从不调用模型。

渠道 来源 强项 局限
静态 UI 字段 源码 registerCommand / new SettingsList / items: [ 区域里 description / hint 等字段与 key 成对出现的位置 形态规范,自带归属 看不到藏在函数里的文案
形态候选 文件名像面板模块的文件里,形态像文案的字面量 能捡到少见的字段名和函数拼出来的文案 选不准;与其它候选一样一律翻译,不逐条判断(ADR 0007)
运行时命令 会话内 pi.getCommands() + pi 内置命令表 命令描述的唯一权威来源 只有命令,没有面板文案

命令行工具读不到活的命令列表,改读扩展写的会话快照。

改译文:重新生成,不要手改

语言包是生成物,不是源码。手改的值下一次 /localize 就没了,而且会掩盖造成缺口的扫描 bug。

译文不对 → 跑 /localize → 全量重建。某条文案干脆生成不出来,那是扫描器的 bug(缺一条渠道或一个候选 位置),修工具而不是补包。类别与键的约束:

  1. 键是冻结的:COMMANDS 键是命令名,ARGS 键是 命令/参数,DESCRIPTIONS 键是英文原文。只翻值。
  2. 占位符保留:{name}。
  3. 术语保持英文:清单在 lib/terms.mjs 的 KEEP_ENGLISH。
  4. 注释与文档用中文,值和注释同语言。
  5. 本扩展自己的文案放 lang/ui/<code>.mjs,绝不进 pi 语言包。

排错

什么都没翻译。 看 localize.config.json 的当前语言(或跑 /localize 看哪一行有 ✔)。英文就是「不翻译」, 也是默认值;语言包缺失同样回退到它,而不是报错。

有个别文案还是英文。 两种常见原因:那条文案属于暂不翻译的类别(对话框标题、空状态、状态标签);或者它 是插件在你上次生成之后新加的。后者跑 /localize → 全量重建。

译文读着别扭。 别改包,跑 /localize → 全量重建。

想要的语言不在列表里。 见 语言。

开发

没有构建步骤:pi 用 jiti 直接加载 index.ts,扩展是带 JSDoc 类型的普通 ESM。

pi -e ./index.ts          # 试用一次,不安装
pi install -l .           # 把 checkout 注册为项目包(.pi/settings.json)
pi install "$PWD"         # 注册到本机

会话里 /reload 就能吃到代码改动。

npm test                  # 有语言包的检查 + 全新安装(零包)状态
npm run test:packs        # 快循环:只跑有语言包的检查
npm run test:zero-pack    # 模拟刚 pi install 的状态
npm run test:guards       # 每条 DESCRIPTIONS 键都能重新生成?没有行标题混入?(读本机插件)
npm run lint              # ESLint(只 lint *.mjs,最小规则集)
npm run format:check      # Prettier(代码与配置;*.md 与生成物不在范围)
npm run scan              # 已装插件的 UI 文案覆盖率
node scan.mjs --json      # 机器可读的缺口清单
node scan.mjs --all       # 忽略覆盖率(重建视图)

check.mjs 有两种状态,都必须绿:

  1. 有语言包 —— 你的 checkout 通常有 lang/<code>.mjs,翻译相关的断言会跑;
  2. 零包 —— 刚 pi install 的样子(只有 lang/languages.mjs 和 lang/ui/en.mjs)。依赖语言包的断言 跳过 而不是失败。npm test 会在临时目录里造出这个状态再跑一遍自检。

自检还会真的跑一遍扩展接线(假的 pi + session_start / turn_start):只 import 是看不出回调里写错的。

目录结构

index.ts                     接线:状态 + 钩子 + session/turn 事件
lib/categories.mjs           翻译类别注册表(一类文案 = 一张表 + 一个渠道 + 一个应用点)
lib/packs.mjs                语言包加载:唯一知道包形状与磁盘布局的地方
lib/tables.mjs               语言包 → 翻译逻辑(纯函数)
lib/hooks/autocomplete.mjs   "/" 面板命令 / 参数描述
lib/hooks/panels.mjs         活的组件树 + 实例 render(只改 description)
lib/commands/localize.mjs    /localize:选择器、切换、生成
lib/plugin-scan.mjs          三条覆盖渠道
lib/command-list.mjs         命令列表会话快照(给 scan / check 用)
lib/translate-prompt.mjs     生成「翻译这个包」的提示词(正文英文,注释中文)
lib/terms.mjs                保持英文的术语
lib/language-picker.mjs      选择器组件
lang/languages.mjs           可选语言
lang/<code>.mjs              pi 界面语言包,按用户生成(开发参考:zh-CN)
lang/ui/<code>.mjs           本扩展自己的界面文案(源:en)
check.mjs  scan.mjs          自检 / 覆盖率扫描
eslint.config.mjs            ESLint flat config(最小集,无插件)
.prettierrc.json             Prettier 选项(tabWidth 1,与现有代码一致)
test/all.mjs                 npm test 的入口
test/zero-pack.mjs           在模拟的全新安装上跑 check.mjs
test/pack-guards.mjs         重建安全:每条键都能重新发现?没有行标题?
CONTEXT.md                   领域术语表
docs/adr/                    关键决定

设计说明

  • 不 patch 类。 pi 用 jiti 加载扩展,import 到的 pi-tui 类和运行中 bundle 用的不是同一个类对象。 只能改活对象:组件树。
  • 不做整屏行替换。 那会改到聊天正文、页脚和其它组件。作用域只能是面板自己的输出。
  • 只改 description。 label / values / currentValue 被查表、搜索、循环使用。
  • 缺语言包是正常状态,不是错误:扩展照常加载、回退英文,/localize 生成缺的部分。
  • 包形状只定义一次(lib/categories.mjs + lib/packs.mjs),运行时、scan.mjs、check.mjs 共用。

隐私

  • 没有遥测、没有网络请求;扩展自己从不联系模型。
  • /localize 只是把提示词发进你当前会话,走你自己配置的 provider 和账号。
  • 命令快照只含命令名与描述,落在系统临时目录。

许可

MIT