npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

pi-localize

v1.1.0

Published

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

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