@eevee-ta/cli 0.1.0-beta.1
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 +492 -0
- package/assets/skills/eevee-mcp/SKILL.md +127 -0
- package/assets/skills/eevee-mcp/reference.md +105 -0
- package/assets/skills/eevee-migration/SKILL.md +181 -0
- package/assets/skills/eevee-project-setup/SKILL.md +266 -0
- package/dist/src/bin/cli.js +237 -0
- package/dist/src/bin/cli.js.map +1 -0
- package/dist/src/commands/business-command.js +340 -0
- package/dist/src/commands/business-command.js.map +1 -0
- package/dist/src/commands/config-command.js +71 -0
- package/dist/src/commands/config-command.js.map +1 -0
- package/dist/src/commands/intl-command.js +131 -0
- package/dist/src/commands/intl-command.js.map +1 -0
- package/dist/src/commands/lint-command.js +105 -0
- package/dist/src/commands/lint-command.js.map +1 -0
- package/dist/src/commands/mcp-command.js +167 -0
- package/dist/src/commands/mcp-command.js.map +1 -0
- package/dist/src/commands/skill-command.js +116 -0
- package/dist/src/commands/skill-command.js.map +1 -0
- package/dist/src/lib/args.js +77 -0
- package/dist/src/lib/args.js.map +1 -0
- package/dist/src/lib/business-catalog.js +445 -0
- package/dist/src/lib/business-catalog.js.map +1 -0
- package/dist/src/lib/config.js +69 -0
- package/dist/src/lib/config.js.map +1 -0
- package/dist/src/lib/intl-catalog.js +58 -0
- package/dist/src/lib/intl-catalog.js.map +1 -0
- package/dist/src/lib/intl-config.js +125 -0
- package/dist/src/lib/intl-config.js.map +1 -0
- package/dist/src/lib/intl-downloader.js +217 -0
- package/dist/src/lib/intl-downloader.js.map +1 -0
- package/dist/src/lib/intl-serializers/csv.js +25 -0
- package/dist/src/lib/intl-serializers/csv.js.map +1 -0
- package/dist/src/lib/intl-serializers/custom.js +23 -0
- package/dist/src/lib/intl-serializers/custom.js.map +1 -0
- package/dist/src/lib/intl-serializers/index.js +22 -0
- package/dist/src/lib/intl-serializers/index.js.map +1 -0
- package/dist/src/lib/intl-serializers/js.js +10 -0
- package/dist/src/lib/intl-serializers/js.js.map +1 -0
- package/dist/src/lib/intl-serializers/json.js +7 -0
- package/dist/src/lib/intl-serializers/json.js.map +1 -0
- package/dist/src/lib/intl-serializers/properties.js +43 -0
- package/dist/src/lib/intl-serializers/properties.js.map +1 -0
- package/dist/src/lib/intl-serializers/ts.js +16 -0
- package/dist/src/lib/intl-serializers/ts.js.map +1 -0
- package/dist/src/lib/intl-serializers/xml.js +21 -0
- package/dist/src/lib/intl-serializers/xml.js.map +1 -0
- package/dist/src/lib/json.js +40 -0
- package/dist/src/lib/json.js.map +1 -0
- package/dist/src/lib/lint-config.js +180 -0
- package/dist/src/lib/lint-config.js.map +1 -0
- package/dist/src/lib/lint-java.js +226 -0
- package/dist/src/lib/lint-java.js.map +1 -0
- package/dist/src/lib/lint-types.js +2 -0
- package/dist/src/lib/lint-types.js.map +1 -0
- package/dist/src/lib/lint-web.js +183 -0
- package/dist/src/lib/lint-web.js.map +1 -0
- package/dist/src/lib/lint.js +192 -0
- package/dist/src/lib/lint.js.map +1 -0
- package/dist/src/lib/mcp-client.js +185 -0
- package/dist/src/lib/mcp-client.js.map +1 -0
- package/dist/src/lib/output.js +34 -0
- package/dist/src/lib/output.js.map +1 -0
- package/dist/src/lib/skill-installer.js +123 -0
- package/dist/src/lib/skill-installer.js.map +1 -0
- package/dist/src/lib/tool-docs.js +66 -0
- package/dist/src/lib/tool-docs.js.map +1 -0
- package/dist/src/lib/types.js +2 -0
- package/dist/src/lib/types.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# @eevee/cli reference for Agents
|
|
2
|
+
|
|
3
|
+
## Command model
|
|
4
|
+
|
|
5
|
+
1. **Business layer (preferred):** stable English `<group> <action>` commands with typed options, Bearer-token auth and response unwrapping handled by the CLI.
|
|
6
|
+
2. **Raw MCP layer (fallback/debugging):** tools/list, resources/*, prompts/*, arbitrary requests and notifications.
|
|
7
|
+
|
|
8
|
+
Never call HTTP REST endpoints directly unless the user explicitly asks; route through MCP so session negotiation and auditing stay consistent.
|
|
9
|
+
|
|
10
|
+
## Configuration
|
|
11
|
+
|
|
12
|
+
| Source | Example |
|
|
13
|
+
|---|---|
|
|
14
|
+
| Persistent file | `eevee config set --url http://127.0.0.1:10001/mcp --token <token>` |
|
|
15
|
+
| Per command | `eevee project list --url <mcp-url> --token <token>` |
|
|
16
|
+
| Environment | `EEVEE_MCP_URL=<url> EEVEE_TOKEN=<token> eevee doctor` |
|
|
17
|
+
|
|
18
|
+
Precedence is flags → environment → `~/.eevee-cli/config.json` → built-in local URL. The config file is created with mode `0600`.
|
|
19
|
+
|
|
20
|
+
## Business discovery
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
eevee business # all packaged operations grouped by domain
|
|
24
|
+
eevee <group> <action> --help
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Domains included: project, version, term, translation, tag-group, tag, permission, log, profile, config, and system user. Every delete/clear command is guarded by `--yes`.
|
|
28
|
+
|
|
29
|
+
### Representative lifecycle
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Projects
|
|
33
|
+
eevee project list --json
|
|
34
|
+
eevee project create --name Demo --locales zh-CN,en-US --json
|
|
35
|
+
eevee project update --id 86 --description 'Updated by CLI'
|
|
36
|
+
eevee project delete 86 --yes --json
|
|
37
|
+
|
|
38
|
+
# Versions and terms
|
|
39
|
+
eevee version list 86
|
|
40
|
+
eevee version create --id 86 --name v1
|
|
41
|
+
eevee term list 86
|
|
42
|
+
eevee term set-tags --id 86 --version-id 9 --term-id 22 --tag-ids 3,4
|
|
43
|
+
|
|
44
|
+
# Translations
|
|
45
|
+
eevee translation set-content --id 86 --term-id 22 --locale en-US --content Hello
|
|
46
|
+
eevee translation set-status --id 86 --term-id 22 --locale en-US --status 3
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Use the returned IDs from live responses rather than examples above.
|
|
50
|
+
|
|
51
|
+
## Built-in MCP tool fallbacks
|
|
52
|
+
|
|
53
|
+
| Server tool | Purpose | Invocation |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `list_api_operations` | Search Swagger-derived REST operations by method/tag/text; returns pagination and `operation_id`. | `eevee tools call list_api_operations '{"method":"GET","search":"terms","limit":50}'` |
|
|
56
|
+
| `get_api_operation` | Return one operation's contract: path/query/header parameters and JSON body schema. | `eevee tools call get_api_operation '{"operation_id":"<id>"}'` |
|
|
57
|
+
| `call_api_operation` | Execute an operation as the authenticated token owner using `parameters.path/query` plus `body`. | `eevee tools call call_api_operation '{"operation_id":"<id>","parameters":{"id":1},"body":{}}'` |
|
|
58
|
+
|
|
59
|
+
Check `eevee tools list` first; it is authoritative if the server adds tools later. Read detailed schemas and offline workflow notes with `eevee tools docs [tool-name]`.
|
|
60
|
+
|
|
61
|
+
## Full MCP surface
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
eevee ping
|
|
65
|
+
eevee tools list [--raw|--json]
|
|
66
|
+
eevee tools docs [tool]
|
|
67
|
+
eevee tools call <tool> '<arguments-json>' # also supports @payload.json / --args @file.json
|
|
68
|
+
eevee resources list | templates | read <uri>
|
|
69
|
+
eevee resources subscribe <uri>
|
|
70
|
+
eevee prompts list
|
|
71
|
+
eevee prompts get <name> --args '{"key":"value"}'
|
|
72
|
+
eevee request completion/complete '{"ref":{"type":"ref/prompt","name":"review"},"argument":{"name":"code","value":"..."}}'
|
|
73
|
+
eevee notify notifications/cancelled '{"requestId":"<id>","reason":"cancelled"}'
|
|
74
|
+
eevee request logging/setLevel '{"level":"info"}'
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Every network command completes MCP initialize + initialized handshake over Streamable HTTP, sends `Authorization: Bearer <user-token>`, and preserves `Mcp-Session-Id` automatically.
|
|
78
|
+
|
|
79
|
+
## Output conventions
|
|
80
|
+
|
|
81
|
+
- Human output unwraps REST `{status,data,msg}` envelopes and renders arrays as aligned tables.
|
|
82
|
+
- `--json` prints `{ok:true,data}` or `{ok:false,data}`.
|
|
83
|
+
- `--raw` prints the full MCP CallToolResult including content blocks and structured content.
|
|
84
|
+
- Empty REST data prints `(空)` instead of implying failure.
|
|
85
|
+
|
|
86
|
+
## Skill installation
|
|
87
|
+
|
|
88
|
+
Default Codex + Claude global copy:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
eevee skills install
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Target examples:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
eevee skills install codex # $CODEX_HOME/skills/eevee-mcp
|
|
98
|
+
eevee skills install claude # $CLAUDE_CONFIG_DIR/skills/eevee-mcp
|
|
99
|
+
eevee skills install universal # ~/.agents/skills/eevee-mcp
|
|
100
|
+
eevee skills install codex,claude --project .
|
|
101
|
+
eevee skills install universal --dir .agents/skills
|
|
102
|
+
eevee skills update # replace bundled-skill managed copies
|
|
103
|
+
eevee skills uninstall --yes # explicit removal
|
|
104
|
+
eevee skills paths # inspect destination roots
|
|
105
|
+
```
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eevee-migration
|
|
3
|
+
description: Guide i18n term migration from code repositories into eevee — incremental versioning, param extraction, Git source_info, deduplication, and API-first operations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# eevee i18n 迁移技能
|
|
7
|
+
|
|
8
|
+
当需要将代码仓库中的 i18n 词条迁移到 eevee 平台时使用此技能。
|
|
9
|
+
核心原则:**所有操作走 API,不直接修改数据库**。
|
|
10
|
+
|
|
11
|
+
## 操作人规范
|
|
12
|
+
|
|
13
|
+
- 统一使用超管用户(如 id=1)的 token,不要通过 mock 登录创建多余用户
|
|
14
|
+
- Token 通过 `Authorization: Bearer <token>` 传递
|
|
15
|
+
- 不确定 token 时先用 `GET /api/v1/users` 确认用户身份
|
|
16
|
+
|
|
17
|
+
## 完整迁移流程
|
|
18
|
+
|
|
19
|
+
### 第一步:切换代码仓库分支
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
cd /path/to/repo && git checkout release/X.Y
|
|
23
|
+
git branch --show-current # 确认分支
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 第二步:提取代码中使用的 i18n key
|
|
27
|
+
|
|
28
|
+
**Java 项目(properties + MessageFormat)**:
|
|
29
|
+
|
|
30
|
+
1. 扫描所有 `.java` 文件,匹配以下模式:
|
|
31
|
+
- `getLocaleMessage("key")` / `tryLocaleMessage("key", params)`
|
|
32
|
+
- `new BizException(ReturnCode.XXX, "key", params...)`
|
|
33
|
+
- 字符串字面量 `"gaia.xxx.yyy"`(带包名前缀)
|
|
34
|
+
2. 扫描枚举文件(`ReturnCode.java` 等),提取 `localeMsgRef` 值
|
|
35
|
+
3. 读取 `messages_zh_CN.properties` 获取所有已翻译 key
|
|
36
|
+
4. 计算交集:`matched = codeKeys ∩ propsKeys`
|
|
37
|
+
|
|
38
|
+
**前端项目(JSON/tsx formatMessage)**:
|
|
39
|
+
|
|
40
|
+
1. 扫描 `intl.tsx`/`intl.ts` 文件,匹配 `formatMessage({ id: 'key' }, { 0: x })`
|
|
41
|
+
2. 从函数签名提取参数名和类型(`x: number` → 数量,`x: ReactNode` → 名称)
|
|
42
|
+
3. 通过英文内容反向搜索匹配未直接引用的 key
|
|
43
|
+
|
|
44
|
+
### 第三步:对比上一版本获取增量
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
新增 key = 当前版本 matched - 上一版本 matched
|
|
48
|
+
删除 key = 上一版本 matched - 当前版本 matched
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
只将**新增 key** 迁移到新版本(增量模式),不重复已有词条。
|
|
52
|
+
|
|
53
|
+
### 第四步:通过 API 创建版本
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
curl -X POST /api/v1/projects/{projectId}/versions \
|
|
57
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
58
|
+
-H "Content-Type: application/json" \
|
|
59
|
+
-d '{"name": "release-X.Y"}'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
⚠️ 如果同名版本软删后唯一键冲突,需要应用层在软删时改名(`name__del__{id}`)或硬删旧记录。
|
|
63
|
+
|
|
64
|
+
### 第五步:通过 API 创建词条(含翻译、描述、参数)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
curl -X POST /api/v1/projects/{projectId}/versions/{versionId}/terms \
|
|
68
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
69
|
+
-H "Content-Type: application/json" \
|
|
70
|
+
-d '{
|
|
71
|
+
"name": "gaia.service.error.xxx",
|
|
72
|
+
"description": "模块:错误描述",
|
|
73
|
+
"params": [{"name":"count","value":"1","desc":"数量"}],
|
|
74
|
+
"translations": {"zh-CN":"中文","en-US":"English","ja-JP":"日本語","ko-KR":"한국어"}
|
|
75
|
+
}'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**描述生成规则**:
|
|
79
|
+
从 key 路径推断模块前缀 + zh-CN 内容:
|
|
80
|
+
`gaia.service.workflow.error.task_check.xxx` → `"任务校验:xxx"`
|
|
81
|
+
|
|
82
|
+
**参数提取规则**:
|
|
83
|
+
扫描 zh-CN 翻译中的 `{0}` `{1}` 占位符,结合上下文推断:
|
|
84
|
+
|
|
85
|
+
| 上下文 | 推断 | 示例 |
|
|
86
|
+
|--------|------|------|
|
|
87
|
+
| `{0}` 后跟 个/条/项 | count | `{"name":"count","value":"1","desc":"数量(个)"}` |
|
|
88
|
+
| `{0}` 成功 + `{1}` 失败 | successCount/failCount | `{"name":"successCount","value":"1","desc":"成功数"}` |
|
|
89
|
+
| `【{0}】` 括号内 + 表 | tableName | `{"name":"tableName","value":"table_name","desc":"表名"}` |
|
|
90
|
+
| `{0}` + 原因/失败 | errorMsg | `{"name":"errorMsg","value":"错误详情","desc":"错误信息"}` |
|
|
91
|
+
| 通知模板 `{0}`~`{4}` | 依次: 空间/时间/名称/原因/链接 | 见下方模板映射 |
|
|
92
|
+
|
|
93
|
+
通知模板映射:
|
|
94
|
+
`{0}`→spaceName, `{1}`→timestamp, `{2}`→flowName/taskName, `{3}`→failReason, `{4}`→detailUrl
|
|
95
|
+
|
|
96
|
+
⚠️ **同一词条内参数名不可重复**。如两个占位符推断出同名(如两个 `tableName`),需根据位置区分(如 `spaceName` + `tableName`)。
|
|
97
|
+
|
|
98
|
+
**source_info(Git 信息)**:
|
|
99
|
+
API 要求 `repo/branch/path/line` 四字段完整或全部留空:
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"repo": "https://gitlab.example.com/team/repo",
|
|
104
|
+
"branch": "release/6.1",
|
|
105
|
+
"path": "gaia-common/src/main/java/.../ReturnCode.java",
|
|
106
|
+
"line": 0
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
通过已有词条 PATCH 补充:
|
|
111
|
+
```bash
|
|
112
|
+
curl -X PATCH /api/v1/projects/{projectId}/terms/{termId} \
|
|
113
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
114
|
+
-H "Content-Type: application/json" \
|
|
115
|
+
-d '{"source_info": {...}, "params": [...]}'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 第六步:去重(新版本不含旧版本已有的词条)
|
|
119
|
+
|
|
120
|
+
对比新旧版本的 term name 集合,删除新版本中与旧版本重复的:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
V6.0 增量 = V6.0 全量 keys - V5.0 keys
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
逐个通过 `DELETE /api/v1/projects/{projectId}/terms/{termId}` 删除。
|
|
127
|
+
|
|
128
|
+
### 第七步:清理"待分类"中的重复词条
|
|
129
|
+
|
|
130
|
+
新版本发布后,"待分类"中与正式版本重复的词条应删除,只保留独有词条。
|
|
131
|
+
|
|
132
|
+
## 质量检查
|
|
133
|
+
|
|
134
|
+
### 遗漏 key 报告
|
|
135
|
+
|
|
136
|
+
分类输出:
|
|
137
|
+
|
|
138
|
+
| 分类 | 说明 |
|
|
139
|
+
|------|------|
|
|
140
|
+
| 代码引用但 properties 缺失 | 枚举或代码中定义了 key 但 properties 里没翻译 |
|
|
141
|
+
| properties 有但代码未引用 | 历史遗留或预留 |
|
|
142
|
+
| 前缀 key(尾带 `.`) | 动态拼接,非缺失 |
|
|
143
|
+
| 误报 | 非 i18n 字符串被正则误匹配 |
|
|
144
|
+
|
|
145
|
+
### 参数覆盖率
|
|
146
|
+
|
|
147
|
+
检查翻译中含 `{N}` 但 params 为空的词条,通过 PATCH 补齐。
|
|
148
|
+
|
|
149
|
+
## 常见坑
|
|
150
|
+
|
|
151
|
+
### ❌ 不要做的事
|
|
152
|
+
|
|
153
|
+
1. **不要直接修改数据库**——绕过校验、日志和数据完整性
|
|
154
|
+
2. **不要用 `DELETE /projects/:id/terms` 清空单版本**——这会清空整个项目所有版本的词条
|
|
155
|
+
3. **不要 mock 登录创建多余用户**——统一用超管 token
|
|
156
|
+
4. **不要假设 properties 文件名用横杠**——Java 习惯用下划线(`messages_zh_CN.properties` 不是 `messages_zh-CN.properties`)
|
|
157
|
+
5. **不要用 SQL LIKE 搜索 `__del__`**——`_` 在 LIKE 中是通配符,会误匹配 `delete_failed` 等正常 key
|
|
158
|
+
|
|
159
|
+
### ⚠️ 注意事项
|
|
160
|
+
|
|
161
|
+
1. source_info 四字段要么全填要么全空,不能只填部分
|
|
162
|
+
2. 同一词条的 params 数组中 name 不可重复
|
|
163
|
+
3. 版本删除前必须清空其下所有词条
|
|
164
|
+
4. 软删记录的唯一键冲突需在应用层处理(改名后软删)
|
|
165
|
+
5. 批量 API 调用时控制并发(建议 3~5),避免打垮服务
|
|
166
|
+
|
|
167
|
+
## 多版本增量模式图
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
V4.5(全量 311)
|
|
171
|
+
└── V5.0(增量 184 = 5.0新增key)
|
|
172
|
+
└── V6.0(增量 194 = 6.0新增key)
|
|
173
|
+
└── V6.1(增量 0 = 无新增,复用 V6.0)
|
|
174
|
+
|
|
175
|
+
待分类 = 全量导入 - 各正式版本已有的 key
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
每次切换分支后:
|
|
179
|
+
1. 提取 key → 对比上一版 → 得到增量
|
|
180
|
+
2. 创建新版本 → 创建增量词条
|
|
181
|
+
3. 无增量则不创建新版本,仅更新版本名
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: eevee-project-setup
|
|
3
|
+
description: Guide configuring a frontend or Java backend project to use @eevee/cli for term sync (intl download) and lint (missing-key / hardcoded-text detection). Covers web and Java adapters, file layout, and step-by-step initialization.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# eevee 项目接入技能
|
|
7
|
+
|
|
8
|
+
当需要让一个代码仓库通过 `@eevee/cli` 实现**词条同步**和**国际化检查**时使用此技能。
|
|
9
|
+
核心原则:**所有词条数据通过 API 拉取,配置文件提交到仓库,token 不入 Git**。
|
|
10
|
+
|
|
11
|
+
## 前置条件
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
eevee config set --url http://127.0.0.1:10001/mcp
|
|
15
|
+
eevee config set --token <your-user-token>
|
|
16
|
+
eevee ping
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
确认项目 ID 和版本 ID:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
eevee project list
|
|
23
|
+
eevee intl versions --project <projectId>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## 通用流程
|
|
27
|
+
|
|
28
|
+
1. 确认项目类型(前端 web / 后端 java)
|
|
29
|
+
2. 创建 `.eevee/` 目录存放同步配置
|
|
30
|
+
3. 创建 `.eevee-lint.json`(Java)或在 `package.json` 配置 `eevee.lint`(web)
|
|
31
|
+
4. 运行 `eevee intl download --dry-run` 验证
|
|
32
|
+
5. 运行 `eevee lint` 验证
|
|
33
|
+
6. 把快照目录加入 `.gitignore`(快照不入 Git)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 前端项目(web adapter)
|
|
38
|
+
|
|
39
|
+
前端项目有 `package.json`,配置写入 `eevee` 字段或独立 `.eevee-lint.json`。
|
|
40
|
+
|
|
41
|
+
### package.json
|
|
42
|
+
|
|
43
|
+
```jsonc
|
|
44
|
+
{
|
|
45
|
+
"eevee": {
|
|
46
|
+
"intl": "intl.download.json",
|
|
47
|
+
"lint": {
|
|
48
|
+
"refresh": {
|
|
49
|
+
"config": "intl.download.json"
|
|
50
|
+
},
|
|
51
|
+
"languages": {
|
|
52
|
+
"web": {
|
|
53
|
+
"enabled": true,
|
|
54
|
+
"root": ".",
|
|
55
|
+
"intlConfig": "intl.json",
|
|
56
|
+
"includes": ["src/**/*.{ts,tsx,js,jsx}"],
|
|
57
|
+
"excludes": ["**/*.test.*", "**/mock/**", "**/node_modules/**"],
|
|
58
|
+
"excludeAscii": true,
|
|
59
|
+
"tagMatchMap": {
|
|
60
|
+
"src/**/*": ["<project-tag>"]
|
|
61
|
+
},
|
|
62
|
+
"excludeProperties": ["title", "description"],
|
|
63
|
+
"excludeTrack": true
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### intl.download.json
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
[
|
|
75
|
+
{
|
|
76
|
+
"outPath": ".eevee/locales",
|
|
77
|
+
"format": "json",
|
|
78
|
+
"splitByTag": false,
|
|
79
|
+
"languages": {
|
|
80
|
+
"zh-CN": "zh-CN-<tag-name>"
|
|
81
|
+
},
|
|
82
|
+
"projects": [
|
|
83
|
+
{ "projectId": 1, "tags": [123] }
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### intl.json(lint 数据源)
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"outPaths": [
|
|
94
|
+
{ "path": ".eevee/locales" }
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 运行
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
eevee lint --staged
|
|
103
|
+
eevee lint --language web
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 后端项目(Java adapter)
|
|
109
|
+
|
|
110
|
+
Java 项目(如 Spring Boot)通常没有 `package.json`,推荐在仓库根目录放 `.eevee-lint.json`,
|
|
111
|
+
同步配置放 `.eevee/` 目录。
|
|
112
|
+
|
|
113
|
+
### 目录结构
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
project-root/
|
|
117
|
+
├── .eevee/
|
|
118
|
+
│ ├── sync.json ← 运行时 properties 全量生成
|
|
119
|
+
│ ├── download.json ← lint 用 JSON 快照
|
|
120
|
+
│ ├── intl.json ← lint 数据源声明
|
|
121
|
+
│ └── README.md
|
|
122
|
+
├── .eevee-lint.json ← lint 规则
|
|
123
|
+
└── .gitignore ← 忽略 .eevee/locales/
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### .eevee-lint.json
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"refresh": {
|
|
131
|
+
"config": ".eevee/download.json"
|
|
132
|
+
},
|
|
133
|
+
"languages": {
|
|
134
|
+
"web": { "enabled": false },
|
|
135
|
+
"java": {
|
|
136
|
+
"enabled": true,
|
|
137
|
+
"root": ".",
|
|
138
|
+
"intlConfig": ".eevee/intl.json",
|
|
139
|
+
"includes": ["*/src/main/java/**/*.java"],
|
|
140
|
+
"excludes": ["**/src/test/**", "**/generated/**", "**/target/**"],
|
|
141
|
+
"tagMatchMap": {
|
|
142
|
+
"*/src/main/java/**/*": ["<tag-name>"]
|
|
143
|
+
},
|
|
144
|
+
"localeMethods": ["getLocaleMessage", "tryLocaleMessage", "getMessage"],
|
|
145
|
+
"checkHardcoded": true,
|
|
146
|
+
"excludeMethods": ["trace", "debug", "info", "warn", "error"]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### .eevee/download.json(lint 快照)
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
[
|
|
156
|
+
{
|
|
157
|
+
"outPath": "locales",
|
|
158
|
+
"format": "json",
|
|
159
|
+
"splitByTag": false,
|
|
160
|
+
"languages": {
|
|
161
|
+
"zh-CN": "zh-CN-<tag-name>"
|
|
162
|
+
},
|
|
163
|
+
"projects": [
|
|
164
|
+
{ "projectId": 3, "versions": [2, 29, 30, 31] }
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### .eevee/intl.json
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"outPaths": [
|
|
175
|
+
{ "path": "locales" }
|
|
176
|
+
]
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
> `outPaths` 相对于 `.eevee/intl.json` 自身目录解析,所以 `"locales"` 指向 `.eevee/locales/`。
|
|
181
|
+
|
|
182
|
+
### .eevee/sync.json(运行时 properties 全量生成)
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
[
|
|
186
|
+
{
|
|
187
|
+
"outPath": "<module>/src/main/resources/static/i18n",
|
|
188
|
+
"format": "properties",
|
|
189
|
+
"splitByTag": false,
|
|
190
|
+
"languages": {
|
|
191
|
+
"zh-CN": "messages_zh_CN",
|
|
192
|
+
"en-US": "messages_en_US",
|
|
193
|
+
"ja-JP": "messages_ja_JP",
|
|
194
|
+
"ko-KR": "messages_ko_KR"
|
|
195
|
+
},
|
|
196
|
+
"projects": [
|
|
197
|
+
{
|
|
198
|
+
"projectId": 3,
|
|
199
|
+
"versions": [2, 29, 30, 31],
|
|
200
|
+
"tags": []
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
"options": {
|
|
204
|
+
"properties": { "escape": "none" }
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
]
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
关键点:
|
|
211
|
+
|
|
212
|
+
- `tags: []` 表示不做标签过滤,项目级全量拉取(适用于没有平台标签的后端项目)
|
|
213
|
+
- 语言映射的 value 是文件名前缀(不含 `.properties`),直接生成 `messages_zh_CN.properties`
|
|
214
|
+
- `escape: "none"` 保持 UTF-8 原文,与 Spring Boot `MessageSource` 兼容
|
|
215
|
+
- `outPath` 相对于 `.eevee/` 目录解析,`../` 可以跳出回到仓库根
|
|
216
|
+
|
|
217
|
+
### .gitignore 追加
|
|
218
|
+
|
|
219
|
+
```gitignore
|
|
220
|
+
# eevee lint 本地快照;运行时 properties 由 sync.json 显式同步
|
|
221
|
+
/.eevee/locales/
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 运行
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# 预览运行时同步
|
|
228
|
+
eevee intl download --config .eevee/sync.json --dry-run
|
|
229
|
+
|
|
230
|
+
# 全量生成 properties
|
|
231
|
+
eevee intl download --config .eevee/sync.json
|
|
232
|
+
|
|
233
|
+
# lint(自动刷新快照 + 检查)
|
|
234
|
+
eevee lint --staged --language java
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 无标签项目的特殊处理
|
|
240
|
+
|
|
241
|
+
如果 EEVEE 平台项目没有创建任何标签组:
|
|
242
|
+
|
|
243
|
+
- `tags: []` → 项目级全量拉取
|
|
244
|
+
- 省略 `tags` 且平台无标签 → 自动降级为项目级全量
|
|
245
|
+
- `versions` 省略 → 拉取项目全部版本
|
|
246
|
+
|
|
247
|
+
后端项目推荐显式配置 `versions`,避免新版本迁移后把未发布的 key 拉进当前分支。
|
|
248
|
+
|
|
249
|
+
## 版本升级维护
|
|
250
|
+
|
|
251
|
+
每次创建新 release 版本后:
|
|
252
|
+
|
|
253
|
+
1. 在 EEVEE 通过 API 迁移增量词条
|
|
254
|
+
2. 拿到新 version ID
|
|
255
|
+
3. 追加到 `.eevee/sync.json` 和 `.eevee/download.json` 的 `versions` 数组
|
|
256
|
+
4. 执行 `eevee intl download --config .eevee/sync.json` 刷新 properties
|
|
257
|
+
|
|
258
|
+
## 常见问题
|
|
259
|
+
|
|
260
|
+
| 问题 | 原因 | 解决 |
|
|
261
|
+
|------|------|------|
|
|
262
|
+
| 未读取到任何 zh-CN*.json | `intl.json` 的 `outPaths` 路径不对 | 确认路径相对于 `intl.json` 所在目录 |
|
|
263
|
+
| 平台返回 0 个词条 | 项目没有标签且未配置 `tags: []` | 显式设置 `"tags": []` |
|
|
264
|
+
| token 过期 401 | `~/.eevee-cli/config.json` 里的 token 失效 | `eevee config set --token <new>` |
|
|
265
|
+
| 全量 sync 后 diff 很大 | key 顺序按平台排序 | 一次性重排,后续 diff 只看新增/删除 |
|
|
266
|
+
| properties 某行换行 | 翻译里含物理换行 | 已在 CLI 修复,确保使用最新版本 |
|