pi-extensions-i18n 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,42 +1,89 @@
1
1
  # pi-extensions-i18n
2
2
 
3
- Shared i18n runtime for pi extensions, with bilingual (zh-CN / en-US) support.
3
+ Shared localization runtime for Pi extensions. It provides a small, catalog-backed API for `zh-CN`, `en-US`, and automatic locale selection.
4
4
 
5
- pi 扩展的公共中英文运行时。提供:
5
+ ## Why a shared package
6
6
 
7
- - `zh-CN`、`en-US` `auto` 三种语言偏好;
8
- - 统一读取 `~/.pi/agent/extensions/pi-extensions-i18n/config.json`;
9
- - `/pi-language` 终端交互式语言配置命令;
10
- - `PI_EXTENSIONS_LOCALE` 环境变量覆盖配置;
11
- - 面向 UI、命令描述和 agent prompt 的翻译器,以及外部 JSON catalog 加载和校验。
7
+ Independent Pi extensions still need the same operational pieces: a portable configuration path, locale precedence, fallback behavior, catalog validation, and parameter interpolation. Keeping those pieces here lets feature packages concentrate on their own behavior while keeping user-facing messages consistent.
12
8
 
13
- ## Install / 安装
9
+ ## Features
10
+
11
+ - `zh-CN`, `en-US`, and `auto` locale preferences.
12
+ - Persistent setting at `~/.pi/agent/extensions/pi-extensions-i18n/config.json`.
13
+ - `PI_EXTENSIONS_LOCALE` environment-variable override.
14
+ - `/pi-language` interactive command, plus `/pi-language en-US` direct selection.
15
+ - Catalog loading and validation requiring both language entries for every message key.
16
+ - Translator interpolation for user-facing UI, command descriptions, and agent prompts.
17
+
18
+ ## Install
14
19
 
15
20
  ```bash
16
21
  pi install npm:pi-extensions-i18n
17
22
  ```
18
23
 
19
- 本包是共享 peer dependency,依赖它的扩展(如 `pi-distill`、`pi-tool-supervisor`)会自动引用,不会把配置复制到每个插件目录。
24
+ Feature packages such as `pi-distill` and `pi-tool-supervisor` use it as a shared dependency. Install it explicitly when you want the locale command by itself.
20
25
 
21
- ## Locale priority / 语言优先级
26
+ Reload Pi after installation:
22
27
 
23
28
  ```text
24
- PI_EXTENSIONS_LOCALE 环境变量 > 持久化配置 > 默认 zh-CN
29
+ /reload
25
30
  ```
26
31
 
27
- `PI_EXTENSIONS_LOCALE` 和配置文件支持 `zh-CN`、`en-US`、`auto`,也接受 `zh`、`en` 简写。`auto` 根据 `LC_ALL`、`LC_MESSAGES` 或 `LANG` 判断系统语言。
32
+ ## Locale precedence
33
+
34
+ ```text
35
+ PI_EXTENSIONS_LOCALE environment variable
36
+ > persisted config
37
+ > default zh-CN
38
+ ```
39
+
40
+ The `auto` preference checks `LC_ALL`, `LC_MESSAGES`, and `LANG`; Chinese system locales resolve to `zh-CN`, and other locales resolve to `en-US`. `zh` and `en` are accepted as short aliases.
41
+
42
+ Examples:
28
43
 
29
44
  ```bash
30
45
  PI_EXTENSIONS_LOCALE=en-US pi
31
46
  ```
32
47
 
33
- 在 pi 中执行 `/pi-language` 可通过 select 菜单保存语言;也可以直接执行 `/pi-language en-US`。
48
+ ```text
49
+ /pi-language en-US
50
+ ```
51
+
52
+ ## Extension author API
53
+
54
+ The package exports the locale and catalog primitives used by the feature packages:
55
+
56
+ ```ts
57
+ import {
58
+ createTranslator,
59
+ getLocale,
60
+ loadCatalog,
61
+ } from "pi-extensions-i18n";
62
+
63
+ const messages = loadCatalog(new URL("../locales/messages.json", import.meta.url));
64
+ const i18n = createTranslator(messages);
65
+
66
+ i18n.t("description");
67
+ getLocale();
68
+ ```
69
+
70
+ Catalog entries must contain both locale keys:
71
+
72
+ ```json
73
+ {
74
+ "description": {
75
+ "zh-CN": "扩展描述",
76
+ "en-US": "Extension description"
77
+ }
78
+ }
79
+ ```
34
80
 
35
- ## Catalog layout / 翻译资源约定
81
+ Invalid catalogs fail during loading, which makes missing translations visible in tests and CI instead of silently leaking a single-language message to users.
36
82
 
37
- 扩展自己的翻译资源保留在对应包的 `locales/` 目录中,按源码模块拆分为 JSON 文件,例如 `pi-distill/locales/summary-utils.json`;本包自身的 `/pi-language` 文案位于 `locales/command.json`。
83
+ ## Requirements
38
84
 
39
- 每个 catalog 条目必须同时包含 `zh-CN` `en-US` 两个语言键(CI 强制检查)。运行时只共享语言解析、配置存储、catalog 校验和插值规则,避免各插件重复实现配置路径和 fallback。
85
+ - Node.js 22 or newer.
86
+ - Pi's extension runtime when using the `/pi-language` command.
40
87
 
41
88
  ## License
42
89
 
@@ -0,0 +1,90 @@
1
+ # pi-extensions-i18n
2
+
3
+ Pi 扩展公共国际化运行时。它提供基于 catalog 的小型 API,支持 `zh-CN`、`en-US` 和自动语言选择。
4
+
5
+ ## 为什么需要公共包
6
+
7
+ 独立的 Pi 扩展仍然需要相同的基础能力:可移植的配置路径、语言优先级、fallback、catalog 校验和参数插值。把这些能力集中在这里,功能包就可以专注于自身逻辑,同时保持用户可见文案的一致性。
8
+
9
+ ## 能力
10
+
11
+ - 支持 `zh-CN`、`en-US` 和 `auto` 语言偏好。
12
+ - 将设置持久化到 `~/.pi/agent/extensions/pi-extensions-i18n/config.json`。
13
+ - 支持 `PI_EXTENSIONS_LOCALE` 环境变量覆盖。
14
+ - 提供 `/pi-language` 交互式命令,也支持 `/pi-language en-US` 直接设置。
15
+ - 加载并校验 catalog,要求每个消息 key 同时提供两种语言。
16
+ - 为 UI、命令描述和 Agent prompt 提供用户文案插值。
17
+
18
+ ## 安装
19
+
20
+ ```bash
21
+ pi install npm:pi-extensions-i18n
22
+ ```
23
+
24
+ `pi-distill`、`pi-tool-supervisor` 等功能包会把它作为公共依赖使用。如果只需要语言命令,也可以单独安装本包。
25
+
26
+ 安装后重新加载 Pi:
27
+
28
+ ```text
29
+ /reload
30
+ ```
31
+
32
+ ## 语言优先级
33
+
34
+ ```text
35
+ PI_EXTENSIONS_LOCALE 环境变量
36
+ > 持久化配置
37
+ > 默认 zh-CN
38
+ ```
39
+
40
+ 选择 `auto` 时会检查 `LC_ALL`、`LC_MESSAGES` 和 `LANG`:中文系统语言解析为 `zh-CN`,其他语言解析为 `en-US`。同时接受 `zh` 和 `en` 简写。
41
+
42
+ 示例:
43
+
44
+ ```bash
45
+ PI_EXTENSIONS_LOCALE=en-US pi
46
+ ```
47
+
48
+ ```text
49
+ /pi-language en-US
50
+ ```
51
+
52
+ ## 扩展作者 API
53
+
54
+ 本包导出功能扩展使用的语言和 catalog 原语:
55
+
56
+ ```ts
57
+ import {
58
+ createTranslator,
59
+ getLocale,
60
+ loadCatalog,
61
+ } from "pi-extensions-i18n";
62
+
63
+ const messages = loadCatalog(new URL("../locales/messages.json", import.meta.url));
64
+ const i18n = createTranslator(messages);
65
+
66
+ i18n.t("description");
67
+ getLocale();
68
+ ```
69
+
70
+ catalog 条目必须同时包含两种语言:
71
+
72
+ ```json
73
+ {
74
+ "description": {
75
+ "zh-CN": "扩展描述",
76
+ "en-US": "Extension description"
77
+ }
78
+ }
79
+ ```
80
+
81
+ 无效 catalog 会在加载阶段失败,让缺失翻译在测试和 CI 中暴露,而不是静默向用户泄露单一语言文案。
82
+
83
+ ## 要求
84
+
85
+ - Node.js 22 或更高版本。
86
+ - 使用 `/pi-language` 命令时需要 Pi 扩展运行时。
87
+
88
+ ## 许可证
89
+
90
+ [MIT](../../LICENSE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-extensions-i18n",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Shared i18n catalog loader & translator for pi extensions",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -12,6 +12,7 @@
12
12
  "src",
13
13
  "locales",
14
14
  "README.md",
15
+ "README.zh-CN.md",
15
16
  "tsconfig.json"
16
17
  ],
17
18
  "scripts": {
package/src/index.ts CHANGED
@@ -92,10 +92,12 @@ export function getLocalePreference(): LocalePreference {
92
92
  return DEFAULT_LOCALE_PREFERENCE;
93
93
  }
94
94
 
95
- if (runtimePreference) return runtimePreference;
96
- runtimePreference =
97
- readPersistedPreference(resolveAgentDir()) ?? DEFAULT_LOCALE_PREFERENCE;
98
- return runtimePreference;
95
+ const persisted = readPersistedPreference(resolveAgentDir());
96
+ if (persisted) {
97
+ runtimePreference = persisted;
98
+ return persisted;
99
+ }
100
+ return runtimePreference ?? DEFAULT_LOCALE_PREFERENCE;
99
101
  }
100
102
 
101
103
  function detectSystemLocale(): Locale {
@@ -174,9 +176,10 @@ export function createTranslator<Catalog extends MessageCatalog>(
174
176
  if (!entry) {
175
177
  throw new Error(`Unknown i18n message key: ${String(key)}`);
176
178
  }
177
- const message = entry[getLocale()];
179
+ const locale = getLocale();
180
+ const message = entry[locale];
178
181
  if (message === undefined) {
179
- throw new Error(`Missing ${getLocale()} translation for message key: ${String(key)}`);
182
+ throw new Error(`Missing ${locale} translation for message key: ${String(key)}`);
180
183
  }
181
184
  return interpolate(message, params);
182
185
  },