@harmonyos-arkts/d2h 0.0.0-stage → 0.1.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/.claude-plugin/marketplace.json +13 -0
- package/.claude-plugin/plugin.json +7 -0
- package/README.md +177 -2
- package/agents/android-to-hmos-00-orchestrator.md +312 -0
- package/agents/d2h.md +168 -0
- package/bin/install-opencode.mjs +57 -0
- package/install-opencode.sh +160 -0
- package/opencode/agents.json +16 -0
- package/package.json +43 -4
- package/schemas/android-source-manifest.schema.json +25 -0
- package/schemas/checkpoint-provenance.schema.json +67 -0
- package/schemas/final-acceptance.schema.json +29 -0
- package/schemas/managed-evidence-index.schema.json +15 -0
- package/schemas/managed-evidence.schema.json +114 -0
- package/schemas/migration-config.schema.json +51 -0
- package/schemas/migration-report-index.schema.json +39 -0
- package/schemas/migration-report-item.schema.json +51 -0
- package/schemas/migration-report-summary.schema.json +25 -0
- package/schemas/migration-status.schema.json +202 -0
- package/schemas/preflight.schema.json +60 -0
- package/schemas/source-order-audit.schema.json +16 -0
- package/schemas/source-provenance-event.schema.json +19 -0
- package/schemas/spec-app-shard.schema.json +45 -0
- package/schemas/spec-fact-corrections-shard.schema.json +13 -0
- package/schemas/spec-features-shard.schema.json +43 -0
- package/schemas/spec-index.schema.json +26 -0
- package/schemas/spec-interactions-shard.schema.json +40 -0
- package/schemas/spec-page.schema.json +98 -0
- package/schemas/spec-pages-index.schema.json +1 -0
- package/schemas/spec-unresolved-shard.schema.json +1 -0
- package/schemas/task-envelope.schema.json +55 -0
- package/schemas/task-plan.schema.json +123 -0
- package/skills/android2hmos_resources_convert/SKILL.md +162 -0
- package/skills/android2hmos_resources_convert/references/image-conversion-rules.md +230 -0
- package/skills/android2hmos_resources_convert/references/svg-fix-patterns.md +175 -0
- package/skills/android2hmos_resources_convert/references/xml-drawable-to-svg-rules.md +513 -0
- package/skills/appgraph-rule-audit/SKILL.md +58 -0
- package/skills/appgraph-rule-audit/references/audit-contract.md +47 -0
- package/skills/appgraph-rule-audit/references/recommendation-schema.md +41 -0
- package/skills/appgraph-rule-audit/schemas/rule-opportunities.schema.json +125 -0
- package/skills/arkts-app-identity/SKILL.md +238 -0
- package/skills/arkts-i18n/SKILL.md +496 -0
- package/skills/arkts-i18n/evals/evals.json +84 -0
- package/skills/arkts-i18n/references/code-examples.md +302 -0
- package/skills/arkts-i18n/references/common-pitfalls.md +391 -0
- package/skills/arkts-i18n/references/dynamic-language-switch.md +604 -0
- package/skills/arkts-i18n/references/hardcoded-string-scanner.md +348 -0
- package/skills/arkts-i18n/references/language-codes.md +104 -0
- package/skills/arkts-i18n/references/resource-file-structure.md +775 -0
- package/skills/arkts-i18n/references/static-vs-dynamic.md +242 -0
- package/skills/arkts-i18n/references/v1-compat.md +244 -0
- package/skills/arkts-i18n/scripts/audit_i18n_completeness.sh +174 -0
- package/skills/arkts-icon-sizing/SKILL.md +211 -0
- package/skills/arkts-icon-sizing/scripts/icon_audit.py +131 -0
- package/skills/arkts-icon-sizing/scripts/icon_autofix.py +88 -0
- package/skills/arkts-icon-sizing/scripts/icon_dims.py +179 -0
- package/skills/arkts-icon-sizing/scripts/icon_fix.py +119 -0
- package/skills/arkts-mvvm-architecture/SKILL.md +613 -0
- package/skills/harmonyos-migration-playbook/SKILL.md +56 -0
- package/skills/harmonyos-migration-playbook/agents/openai.yaml +7 -0
- package/skills/harmonyos-migration-playbook/references/arkts-compile.md +24 -0
- package/skills/harmonyos-migration-playbook/references/harmony-runtime.md +53 -0
- package/skills/harmonyos-migration-playbook/references/lesson-lifecycle.md +45 -0
- package/skills/harmonyos-migration-playbook/references/protocol-e2e.md +23 -0
- package/skills/harmonyos-migration-playbook/references/ui-automation.md +52 -0
- package/skills/harmonyos-migration-playbook/references/windows-environment.md +38 -0
- package/skills/maintaining-migration-report/SKILL.md +155 -0
- package/skills/native-library-substitution/SKILL.md +385 -0
- package/skills/native-library-substitution/references/native-library-substitution.json +56906 -0
- package/skills/native-library-substitution/references/native-library-substitution.md +163 -0
- package/skills/preparing-migration-workspace/SKILL.md +124 -0
- package/skills/preparing-migration-workspace/toolchain.json +43 -0
- package/skills/reviewing-migration-process/SKILL.md +62 -0
- package/src/install-opencode.mjs +110 -0
|
@@ -0,0 +1,775 @@
|
|
|
1
|
+
# 资源文件结构模板
|
|
2
|
+
|
|
3
|
+
> HarmonyOS 应用完整国际化资源目录结构
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 完整目录结构
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
entry/src/main/resources/
|
|
11
|
+
├── base/ # Fallback 资源(当系统语言无匹配时使用)
|
|
12
|
+
│ ├── element/
|
|
13
|
+
│ │ ├── string.json # 字符串资源
|
|
14
|
+
│ │ ├── color.json # 颜色资源
|
|
15
|
+
│ │ ├── float.json # 浮点数资源
|
|
16
|
+
│ │ ├── integer.json # 整数资源
|
|
17
|
+
│ │ └── plural.json # 复数资源
|
|
18
|
+
│ ├── media/ # 图片资源
|
|
19
|
+
│ │ ├── app_icon.png
|
|
20
|
+
│ │ ├── logo.png
|
|
21
|
+
│ │ ├── placeholder.png
|
|
22
|
+
│ │ └── background.png
|
|
23
|
+
│ ├── profile/ # 配置资源
|
|
24
|
+
│ │ ├── main_pages.json
|
|
25
|
+
│ │ └── backup_config.json
|
|
26
|
+
│ └── layout/ # 布局资源(很少用)
|
|
27
|
+
│
|
|
28
|
+
├── zh_CN/ # 简体中文
|
|
29
|
+
│ └── element/
|
|
30
|
+
│ └── string.json
|
|
31
|
+
│
|
|
32
|
+
├── en_US/ # 美国英文
|
|
33
|
+
│ └── element/
|
|
34
|
+
│ └── string.json
|
|
35
|
+
│
|
|
36
|
+
├── en_GB/ # 英国英文
|
|
37
|
+
│ └── element/
|
|
38
|
+
│ └── string.json
|
|
39
|
+
│
|
|
40
|
+
├── zh_TW/ # 繁体中文(台湾)
|
|
41
|
+
│ └── element/
|
|
42
|
+
│ └── string.json
|
|
43
|
+
│
|
|
44
|
+
├── ja/ # 日文
|
|
45
|
+
│ └── element/
|
|
46
|
+
│ └── string.json
|
|
47
|
+
│
|
|
48
|
+
└── dark/ # 深色模式资源(与语言无关)
|
|
49
|
+
├── element/
|
|
50
|
+
│ └── color.json
|
|
51
|
+
└── media/
|
|
52
|
+
└── background_dark.png
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### ⚠️ 重要:base/ 目录不是"中文目录"
|
|
56
|
+
|
|
57
|
+
**base/ 是 Fallback 目录**,当系统语言找不到匹配的资源目录时使用。
|
|
58
|
+
|
|
59
|
+
**常见误解**:
|
|
60
|
+
```markdown
|
|
61
|
+
❌ 错误理解:base/ = 中文目录
|
|
62
|
+
✅ 正确理解:base/ = 无匹配时的 Fallback 目录
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**资源匹配规则**:
|
|
66
|
+
```
|
|
67
|
+
系统语言 = 中文
|
|
68
|
+
↓
|
|
69
|
+
查找:zh、zh_CN、zh_Hans、zh_TW 等
|
|
70
|
+
↓
|
|
71
|
+
找到? → 使用该目录
|
|
72
|
+
找不到? → 使用 base/(Fallback)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**推荐做法**:
|
|
76
|
+
|
|
77
|
+
| 方案 | base/ 内容 | 其他目录 | 适用场景 |
|
|
78
|
+
|------|-----------|---------|---------|
|
|
79
|
+
| **方案 1** | 主要市场语言(如中文) | en_US/ 等 | 单一市场应用 |
|
|
80
|
+
| **方案 2** | 英文或其他通用语言 | zh_CN/、en_US/ 等 | 国际化应用 |
|
|
81
|
+
|
|
82
|
+
**方案 1 示例**(代码仓采用):
|
|
83
|
+
```
|
|
84
|
+
resources/
|
|
85
|
+
├── base/element/string.json # 中文(主要市场)
|
|
86
|
+
└── en_US/element/string.json # 英文
|
|
87
|
+
```
|
|
88
|
+
- 系统中文 → 无 zh 目录 → 使用 base/ → 显示中文 ✅
|
|
89
|
+
- 系统英文 → 找到 en_US → 显示英文 ✅
|
|
90
|
+
|
|
91
|
+
**方案 2 示例**(标准做法):
|
|
92
|
+
```
|
|
93
|
+
resources/
|
|
94
|
+
├── base/element/string.json # 英文(Fallback)
|
|
95
|
+
├── zh_CN/element/string.json # 中文
|
|
96
|
+
└── en_US/element/string.json # 英文
|
|
97
|
+
```
|
|
98
|
+
- 系统中文 → 找到 zh_CN → 显示中文 ✅
|
|
99
|
+
- 系统英文 → 找到 en_US → 显示英文 ✅
|
|
100
|
+
- 其他语言 → 无匹配 → 使用 base/ → 显示英文 ✅
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## string.json 详细格式
|
|
105
|
+
|
|
106
|
+
### 基础格式
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"string": [
|
|
111
|
+
{ "name": "app_name", "value": "应用名称" },
|
|
112
|
+
{ "name": "button_ok", "value": "确定" },
|
|
113
|
+
{ "name": "button_cancel", "value": "取消" }
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 带占位符的字符串
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"string": [
|
|
123
|
+
{ "name": "file_count", "value": "共 %d 个文件" },
|
|
124
|
+
{ "name": "welcome_name", "value": "欢迎,%s" },
|
|
125
|
+
{ "name": "storage_used", "value": "已使用 %s,共 %s" },
|
|
126
|
+
{ "name": "delete_confirm", "value": "确定要删除 %s 吗?" }
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 多行字符串
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"string": [
|
|
136
|
+
{ "name": "terms_of_service", "value": "服务条款\n请仔细阅读以下条款" },
|
|
137
|
+
{ "name": "address_multiline", "value": "北京市朝阳区\n建国路88号\nSOHO现代城" }
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 特殊字符转义
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"string": [
|
|
147
|
+
{ "name": "path_format", "value": "路径:C:\\Users\\test" },
|
|
148
|
+
{ "name": "url_format", "value": "网址:https://example.com?q=a&b=c" },
|
|
149
|
+
{ "name": "quote_example", "value": "他 说:\"你好\"" }
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## 其他资源文件格式
|
|
157
|
+
|
|
158
|
+
### color.json
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"color": [
|
|
163
|
+
{ "name": "primary_color", "value": "#FF007AFF" },
|
|
164
|
+
{ "name": "secondary_color", "value": "#FF5858D6" },
|
|
165
|
+
{ "name": "background_light", "value": "#FFFFFFFF" },
|
|
166
|
+
{ "name": "background_dark", "value": "#FF000000" }
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### float.json
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"float": [
|
|
176
|
+
{ "name": "button_corner_radius", "value": "12.0" },
|
|
177
|
+
{ "name": "text_size_large", "value": "24.0" },
|
|
178
|
+
{ "name": "spacing_medium", "value": "16.0" }
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### integer.json
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"integer": [
|
|
188
|
+
{ "name": "grid_columns", "value": "3" },
|
|
189
|
+
{ "name": "max_retry_count", "value": "5" },
|
|
190
|
+
{ "name": "cache_expire_days", "value": "30" }
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## media 资源组织
|
|
198
|
+
|
|
199
|
+
### 按功能分类
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
base/media/
|
|
203
|
+
├── icon/
|
|
204
|
+
│ ├── home.png
|
|
205
|
+
│ ├── back.png
|
|
206
|
+
│ └── menu.png
|
|
207
|
+
├── image/
|
|
208
|
+
│ ├── logo.png
|
|
209
|
+
│ ├── splash.png
|
|
210
|
+
│ └── placeholder.png
|
|
211
|
+
├── photo/
|
|
212
|
+
│ └── default_avatar.png
|
|
213
|
+
└── other/
|
|
214
|
+
└── watermark.png
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 按语言分类(可选)
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
base/media/
|
|
221
|
+
└── logo.png # 默认 logo
|
|
222
|
+
|
|
223
|
+
en/media/
|
|
224
|
+
└── logo.png # 英文版 logo
|
|
225
|
+
|
|
226
|
+
ja/media/
|
|
227
|
+
└── logo.png # 日文版 logo
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## module.json5 语言声明模板
|
|
233
|
+
|
|
234
|
+
```json5
|
|
235
|
+
{
|
|
236
|
+
"module": {
|
|
237
|
+
"name": "entry",
|
|
238
|
+
"type": "entry",
|
|
239
|
+
"supportedLanguages": [
|
|
240
|
+
"zh-Hans", // 简体中文
|
|
241
|
+
"zh-Hant", // 繁体中文
|
|
242
|
+
"en", // 英文
|
|
243
|
+
"ja", // 日文
|
|
244
|
+
"ko", // 韩文
|
|
245
|
+
"de", // 德文
|
|
246
|
+
"fr", // 法文
|
|
247
|
+
"es", // 西班牙文
|
|
248
|
+
"pt", // 葡萄牙文
|
|
249
|
+
"ru", // 俄文
|
|
250
|
+
"ar", // 阿拉伯文
|
|
251
|
+
"hi", // 印地文
|
|
252
|
+
"th", // 泰文
|
|
253
|
+
"vi", // 越南文
|
|
254
|
+
"id", // 印尼文
|
|
255
|
+
"ms", // 马来文
|
|
256
|
+
"tr", // 土耳其文
|
|
257
|
+
"pl", // 波兰文
|
|
258
|
+
"nl", // 荷兰文
|
|
259
|
+
"it", // 意大利文
|
|
260
|
+
"he", // 希伯来文
|
|
261
|
+
"cs", // 捷克文
|
|
262
|
+
"sv", // 瑞典文
|
|
263
|
+
"da", // 丹麦文
|
|
264
|
+
"fi", // 芬兰文
|
|
265
|
+
"no", // 挪威文
|
|
266
|
+
"el", // 希腊文
|
|
267
|
+
"hu", // 匈牙利文
|
|
268
|
+
"ro", // 罗马尼亚文
|
|
269
|
+
"sk", // 斯洛伐克文
|
|
270
|
+
"uk", // 乌克兰文
|
|
271
|
+
"bg", // 保加利亚文
|
|
272
|
+
"hr", // 克罗地亚文
|
|
273
|
+
"sl", // 斯洛文尼亚文
|
|
274
|
+
"et", // 爱沙尼亚文
|
|
275
|
+
"lv", // 拉脱维亚文
|
|
276
|
+
"lt", // 立陶宛文
|
|
277
|
+
"tl", // 菲律宾文
|
|
278
|
+
"bn", // 孟加拉文
|
|
279
|
+
"ta", // 泰米尔文
|
|
280
|
+
"mr", // 马拉地文
|
|
281
|
+
"te", // 泰卢固文
|
|
282
|
+
"ml", // 马拉雅拉姆文
|
|
283
|
+
"kn", // 卡纳达文
|
|
284
|
+
"gu", // 古吉拉特文
|
|
285
|
+
"pa", // 旁遮普文
|
|
286
|
+
"my", // 缅甸文
|
|
287
|
+
"km", // 高棉文
|
|
288
|
+
"lo", // 老挝文
|
|
289
|
+
"ne", // 尼泊尔文
|
|
290
|
+
"si", // 僧伽罗文
|
|
291
|
+
"ur", // 乌尔都文
|
|
292
|
+
"fa", // 波斯文
|
|
293
|
+
"uz", // 乌兹别克文
|
|
294
|
+
"az", // 阿塞拜疆文
|
|
295
|
+
"ka", // 格鲁吉亚文
|
|
296
|
+
"am" // 阿姆哈拉文
|
|
297
|
+
]
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## AppScope vs Entry 资源
|
|
305
|
+
|
|
306
|
+
### AppScope 资源(应用级)
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
AppScope/
|
|
310
|
+
└── resources/
|
|
311
|
+
├── base/
|
|
312
|
+
│ └── element/
|
|
313
|
+
│ └── string.json # 应用级字符串(如 app_name)
|
|
314
|
+
└── media/
|
|
315
|
+
└── app_icon.png
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Entry 资源(模块级)
|
|
319
|
+
|
|
320
|
+
```
|
|
321
|
+
entry/src/main/resources/
|
|
322
|
+
├── base/
|
|
323
|
+
│ ├── element/
|
|
324
|
+
│ │ └── string.json # 模块级字符串
|
|
325
|
+
│ └── media/
|
|
326
|
+
│ └── module_icon.png
|
|
327
|
+
└── ...
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### 引用优先级
|
|
331
|
+
|
|
332
|
+
1. Entry 模块资源(优先)
|
|
333
|
+
2. AppScope 应用资源(fallback)
|
|
334
|
+
|
|
335
|
+
### 引用方式
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// Entry 模块资源
|
|
339
|
+
$r('app.string.xxx')
|
|
340
|
+
|
|
341
|
+
// AppScope 应用资源
|
|
342
|
+
$r('entry.string.app_name') // ⚠️ 通常不这样用
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
> 建议:所有国际化字符串放在 Entry 模块,避免混淆
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## 当前代码仓实践分析
|
|
350
|
+
|
|
351
|
+
> 基于 SimpleGallery_Arkts 代码仓的实际实现
|
|
352
|
+
|
|
353
|
+
### ⚠️ 重要说明:代码仓的特殊实践
|
|
354
|
+
|
|
355
|
+
**代码仓采用的是"方案 1":base/ 放中文**
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
entry/src/main/resources/
|
|
359
|
+
├── base/element/string.json # 中文(主要市场)
|
|
360
|
+
└── en_US/element/string.json # 英文
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**这种做法的特点**:
|
|
364
|
+
- ✅ 简单:只需维护两个目录
|
|
365
|
+
- ✅ 适合单一市场(中文为主)
|
|
366
|
+
- ⚠️ 不规范:base/ 应该是 Fallback,不是"中文目录"
|
|
367
|
+
- ⚠️ 如果系统语言是日语等,会显示中文(base/)
|
|
368
|
+
|
|
369
|
+
**为什么可以工作?**
|
|
370
|
+
```
|
|
371
|
+
系统语言 = 中文
|
|
372
|
+
↓
|
|
373
|
+
查找:zh、zh_CN、zh_Hans 等
|
|
374
|
+
↓
|
|
375
|
+
找不到? → 使用 base/ → 显示中文 ✅
|
|
376
|
+
|
|
377
|
+
系统语言 = 英文
|
|
378
|
+
↓
|
|
379
|
+
查找:en、en_US 等
|
|
380
|
+
↓
|
|
381
|
+
找到 en_US → 显示英文 ✅
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### 目录结构
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
entry/src/main/resources/
|
|
388
|
+
├── base/ # 中文(默认)
|
|
389
|
+
│ ├── element/
|
|
390
|
+
│ │ ├── string.json # 996 行字符串资源
|
|
391
|
+
│ │ ├── color.json # 颜色资源
|
|
392
|
+
│ │ └── float.json # 浮点数资源
|
|
393
|
+
│ ├── media/ # 图片资源(19+ 文件)
|
|
394
|
+
│ │ ├── camera.png
|
|
395
|
+
│ │ ├── favorite.png
|
|
396
|
+
│ │ └── ...
|
|
397
|
+
│ └── profile/ # 配置资源
|
|
398
|
+
│
|
|
399
|
+
├── en_US/ # 美国英文
|
|
400
|
+
│ └── element/
|
|
401
|
+
│ └── string.json # 996 行(与 base 完全对应)
|
|
402
|
+
│
|
|
403
|
+
├── dark/ # 深色模式
|
|
404
|
+
│ └── element/
|
|
405
|
+
│ └── color.json
|
|
406
|
+
│
|
|
407
|
+
└── rawfile/ # 原始文件
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**关键特性**:
|
|
411
|
+
- ✅ base/ 和 en_US/ 的 string.json **行数完全一致**(996 行)
|
|
412
|
+
- ✅ 所有字符串 key 在两个文件中**完全对应**
|
|
413
|
+
- ✅ 使用 `en_US/` 而非 `en/`(精确区域划分)
|
|
414
|
+
- ✅ 支持深色模式(dark/ 目录)
|
|
415
|
+
- ⚠️ **base/ 放中文**(非标准做法,但适合单一市场应用)
|
|
416
|
+
|
|
417
|
+
**为什么中文系统显示中文?**
|
|
418
|
+
```
|
|
419
|
+
系统语言 = 中文
|
|
420
|
+
↓
|
|
421
|
+
查找:zh、zh_CN 等 → 找不到
|
|
422
|
+
↓
|
|
423
|
+
使用 base/ → base/ 里是中文 → 显示中文 ✅
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**如果您的项目中文系统显示英文,请检查**:
|
|
427
|
+
1. base/element/string.json 的内容是否是中文?
|
|
428
|
+
2. 是否创建了 zh_CN 目录但内容是英文?
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
### 选择 en_US 而非 en 的原因
|
|
433
|
+
|
|
434
|
+
#### 方案对比
|
|
435
|
+
|
|
436
|
+
| 方案 | 目录名 | 优点 | 缺点 | 代码仓选择 |
|
|
437
|
+
|------|--------|------|------|-----------|
|
|
438
|
+
| **简单方案** | `en/` | 简单,适配所有英文区域 | 无法区分不同区域(US/GB/AU) | ❌ 未选择 |
|
|
439
|
+
| **精确方案** | `en_US/` | 精确区域划分,可扩展 | 目录稍多 | ✅ 已选择 |
|
|
440
|
+
|
|
441
|
+
#### 选择 en_US 的三大原因
|
|
442
|
+
|
|
443
|
+
**1. 精确区域划分**
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
en_US/ # 美国英语(代码仓已实现)
|
|
447
|
+
en_GB/ # 英国英语(未来可扩展)
|
|
448
|
+
en_AU/ # 澳大利亚英语(未来可扩展)
|
|
449
|
+
en_CA/ # 加拿大英语(未来可扩展)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
- ✅ 明确标识为美国英语
|
|
453
|
+
- ✅ 与其他英文区域区分(如英国、澳大利亚)
|
|
454
|
+
- ✅ 符合 ISO 3166-1 标准
|
|
455
|
+
|
|
456
|
+
**2. 扩展性好**
|
|
457
|
+
|
|
458
|
+
当前代码仓只支持中英文,但使用 `en_US/` 为未来扩展留出空间:
|
|
459
|
+
|
|
460
|
+
```
|
|
461
|
+
未来可能的扩展:
|
|
462
|
+
├── en_US/ # 已实现
|
|
463
|
+
├── en_GB/ # 可添加:英国英语
|
|
464
|
+
├── ja/ # 可添加:日文
|
|
465
|
+
├── ko/ # 可添加:韩文
|
|
466
|
+
└── zh_TW/ # 可添加:繁体中文
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**3. 代码仓实际情况**
|
|
470
|
+
|
|
471
|
+
- ✅ base/ 和 en_US/ 的 key **完全对应**(996 行)
|
|
472
|
+
- ✅ 所有翻译已完成,维护方便
|
|
473
|
+
- ✅ 新增语言时可直接复制结构
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
### 资源文件对应关系验证
|
|
478
|
+
|
|
479
|
+
**base/element/string.json**(中文,代码仓采用方案 1):
|
|
480
|
+
```json
|
|
481
|
+
{
|
|
482
|
+
"string": [
|
|
483
|
+
{ "name": "module_desc", "value": "图库 - 简单快速的相册应用" },
|
|
484
|
+
{ "name": "app_name", "value": "Gallery_debug" },
|
|
485
|
+
{ "name": "menu_sort", "value": "排序方式" },
|
|
486
|
+
{ "name": "all_photos", "value": "所有照片" },
|
|
487
|
+
{ "name": "favorites", "value": "收藏" },
|
|
488
|
+
// ... 共 996 行
|
|
489
|
+
]
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
**en_US/element/string.json**(英文):
|
|
494
|
+
```json
|
|
495
|
+
{
|
|
496
|
+
"string": [
|
|
497
|
+
{ "name": "module_desc", "value": "Gallery - A simple and fast gallery app" },
|
|
498
|
+
{ "name": "app_name", "value": "Gallery_debug" },
|
|
499
|
+
{ "name": "menu_sort", "value": "Sort by" },
|
|
500
|
+
{ "name": "all_photos", "value": "All Photos" },
|
|
501
|
+
{ "name": "favorites", "value": "Favorites" },
|
|
502
|
+
// ... 共 996 行
|
|
503
|
+
]
|
|
504
|
+
}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
**验证结果**:
|
|
508
|
+
- ✅ 行数一致:996 行
|
|
509
|
+
- ✅ Key 完全对应
|
|
510
|
+
- ✅ Value 类型一致(字符串)
|
|
511
|
+
- ✅ 无语法错误(无尾随逗号)
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
### 代码仓实际使用方式
|
|
516
|
+
|
|
517
|
+
#### 方式 1:静态引用(95%+ 使用)
|
|
518
|
+
|
|
519
|
+
**分布**:遍布所有 `.ets` 文件(270+ 处使用)
|
|
520
|
+
|
|
521
|
+
**示例**:
|
|
522
|
+
```typescript
|
|
523
|
+
// pages/Index.ets:180
|
|
524
|
+
Text($r('app.string.all_photos'))
|
|
525
|
+
|
|
526
|
+
// pages/AboutPage.ets:32
|
|
527
|
+
.title($r('app.string.about_title'))
|
|
528
|
+
|
|
529
|
+
// components/dialogs/ColumnsDialog.ets:56
|
|
530
|
+
Text($r('app.string.dialog_columns_title'))
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
**特点**:
|
|
534
|
+
- ✅ 编译时确定资源路径
|
|
535
|
+
- ✅ 自动跟随系统语言
|
|
536
|
+
- ✅ 无需额外代码
|
|
537
|
+
|
|
538
|
+
#### 方式 2:动态获取(<5% 使用)
|
|
539
|
+
|
|
540
|
+
**位置**:`components/dialogs/ColumnsDialog.ets`
|
|
541
|
+
|
|
542
|
+
**示例**:
|
|
543
|
+
```typescript
|
|
544
|
+
// ColumnsDialog.ets:22
|
|
545
|
+
const resourceManager = context.resourceManager
|
|
546
|
+
const str = resourceManager.getStringByNameSync('dialog_column')
|
|
547
|
+
str = str.replace('%d', num.toString()) // 动态替换占位符
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
**使用场景**:
|
|
551
|
+
- 需要替换占位符(如 `"%d 列"` → `"3 列"`)
|
|
552
|
+
- 需要处理复数(如 `"1 column"` vs `"2 columns"`)
|
|
553
|
+
- 需要判断语言环境
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
### module.json5 配置现状
|
|
558
|
+
|
|
559
|
+
**当前配置**:
|
|
560
|
+
```json5
|
|
561
|
+
{
|
|
562
|
+
"module": {
|
|
563
|
+
"name": "entry",
|
|
564
|
+
"type": "entry",
|
|
565
|
+
"description": "$string:module_desc", // ✅ 使用 $string 引用
|
|
566
|
+
"abilities": [
|
|
567
|
+
{
|
|
568
|
+
"name": "EntryAbility",
|
|
569
|
+
"description": "$string:EntryAbility_desc", // ✅ 使用 $string
|
|
570
|
+
"label": "$string:EntryAbility_label" // ✅ 使用 $string
|
|
571
|
+
}
|
|
572
|
+
]
|
|
573
|
+
// ⚠️ 注意:未配置 supportedLanguages
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**分析**:
|
|
579
|
+
- ✅ description 和 label 支持国际化引用
|
|
580
|
+
- ⚠️ 未配置 `supportedLanguages` 字段
|
|
581
|
+
- 💡 当前实现仍然可以正常工作(系统自动检测)
|
|
582
|
+
|
|
583
|
+
**建议配置**(可选):
|
|
584
|
+
```json5
|
|
585
|
+
{
|
|
586
|
+
"module": {
|
|
587
|
+
"supportedLanguages": ["zh-Hans", "en"] // 明确声明支持的语言
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
### 实现特点总结
|
|
595
|
+
|
|
596
|
+
| 特性 | 实现情况 | 说明 |
|
|
597
|
+
|------|---------|------|
|
|
598
|
+
| **静态引用** | ✅ 95%+ | 主流方式,编译时确定 |
|
|
599
|
+
| **动态获取** | ✅ <5% | 少数场景(占位符、复数) |
|
|
600
|
+
| **动态语言切换** | ❌ 未实现 | 依赖系统语言自动匹配 |
|
|
601
|
+
| **supportedLanguages** | ❌ 未配置 | 可选字段,未配置也能工作 |
|
|
602
|
+
| **资源完整性** | ✅ 完整 | base 和 en_US 完全对应 |
|
|
603
|
+
| **目录命名** | ✅ en_US/ | 精确区域划分 |
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
## ❓ 常见问题排查:中文系统显示英文
|
|
608
|
+
|
|
609
|
+
### 问题现象
|
|
610
|
+
|
|
611
|
+
系统语言是中文,但应用显示英文。
|
|
612
|
+
|
|
613
|
+
### 排查步骤
|
|
614
|
+
|
|
615
|
+
#### 步骤 1:检查 base/ 目录内容
|
|
616
|
+
|
|
617
|
+
**问题**:base/element/string.json 的内容是英文
|
|
618
|
+
|
|
619
|
+
```
|
|
620
|
+
❌ 错误示例:
|
|
621
|
+
resources/base/element/string.json
|
|
622
|
+
{
|
|
623
|
+
"string": [
|
|
624
|
+
{ "name": "app_name", "value": "App Name" }, // 英文!
|
|
625
|
+
{ "name": "hello", "value": "Hello" }
|
|
626
|
+
]
|
|
627
|
+
}
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
**原因**:
|
|
631
|
+
- 系统中文 → 找不到 zh、zh_CN 目录 → 使用 base/
|
|
632
|
+
- base/ 是英文 → 显示英文 ❌
|
|
633
|
+
|
|
634
|
+
**解决方案**:
|
|
635
|
+
|
|
636
|
+
**方案 1:修改 base/ 内容为中文**(代码仓采用)
|
|
637
|
+
```
|
|
638
|
+
✅ 正确示例:
|
|
639
|
+
resources/base/element/string.json
|
|
640
|
+
{
|
|
641
|
+
"string": [
|
|
642
|
+
{ "name": "app_name", "value": "应用名" }, // 中文!
|
|
643
|
+
{ "name": "hello", "value": "你好" }
|
|
644
|
+
]
|
|
645
|
+
}
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
**方案 2:创建 zh_CN 目录**(标准做法)
|
|
649
|
+
```
|
|
650
|
+
✅ 标准做法:
|
|
651
|
+
resources/
|
|
652
|
+
├── base/element/string.json # Fallback(可以是英文)
|
|
653
|
+
├── zh_CN/element/string.json # 中文 ✅
|
|
654
|
+
└── en_US/element/string.json # 英文
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
---
|
|
658
|
+
|
|
659
|
+
#### 步骤 2:检查目录命名
|
|
660
|
+
|
|
661
|
+
**问题**:目录名包含错误字符
|
|
662
|
+
|
|
663
|
+
```
|
|
664
|
+
❌ 错误示例:
|
|
665
|
+
resources/
|
|
666
|
+
└── en_US(element/ ← 括号错误!
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
**解决方案**:重命名目录为 `en_US/element/`
|
|
670
|
+
|
|
671
|
+
---
|
|
672
|
+
|
|
673
|
+
#### 步骤 3:检查系统语言设置
|
|
674
|
+
|
|
675
|
+
确认设备/模拟器的系统语言是中文:
|
|
676
|
+
```
|
|
677
|
+
设置 → 系统和更新 → 语言和输入法 → 语言
|
|
678
|
+
→ 确认是"简体中文"或"中文(简体)"
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
#### 步骤 4:检查 module.json5(可选)
|
|
684
|
+
|
|
685
|
+
**问题**:supportedLanguages 配置不正确
|
|
686
|
+
|
|
687
|
+
```json5
|
|
688
|
+
// ❌ 可能的问题
|
|
689
|
+
"supportedLanguages": ["en"] // 只声明了英文
|
|
690
|
+
|
|
691
|
+
// ✅ 正确配置
|
|
692
|
+
"supportedLanguages": ["zh-Hans", "en"] // 声明中英文
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
### 快速诊断表格
|
|
698
|
+
|
|
699
|
+
| 检查项 | 当前状态 | 问题 | 解决方案 |
|
|
700
|
+
|--------|---------|------|---------|
|
|
701
|
+
| base/string.json 内容 | 英文 | ❌ | 改为中文 |
|
|
702
|
+
| zh_CN 目录 | 不存在 | ⚠️ | 创建或改 base/ |
|
|
703
|
+
| 目录命名 | en_US(element | ❌ | 重命名为 en_US/element |
|
|
704
|
+
| 系统语言 | 非中文 | ❌ | 设置为中文 |
|
|
705
|
+
| supportedLanguages | ["en"] | ⚠️ | 添加 "zh-Hans" |
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
### 最佳实践建议
|
|
710
|
+
|
|
711
|
+
#### 推荐方案(适用于大多数应用)
|
|
712
|
+
|
|
713
|
+
**适用场景**:
|
|
714
|
+
- ✅ 跟随系统语言即可
|
|
715
|
+
- ✅ 无应用内切换需求
|
|
716
|
+
- ✅ 追求简单可靠
|
|
717
|
+
|
|
718
|
+
**实现步骤**:
|
|
719
|
+
|
|
720
|
+
1. **组织资源文件**
|
|
721
|
+
```
|
|
722
|
+
resources/
|
|
723
|
+
├── base/element/string.json # 中文
|
|
724
|
+
└── en_US/element/string.json # 英文
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
2. **确保 key 完全对应**
|
|
728
|
+
- 使用脚本或工具验证
|
|
729
|
+
- 确保行数一致
|
|
730
|
+
|
|
731
|
+
3. **主流使用静态引用**
|
|
732
|
+
```typescript
|
|
733
|
+
Text($r('app.string.xxx'))
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
4. **少数场景使用动态获取**
|
|
737
|
+
```typescript
|
|
738
|
+
const str = resourceManager.getStringByNameSync('key')
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
5. **可选:配置 supportedLanguages**
|
|
742
|
+
```json5
|
|
743
|
+
"supportedLanguages": ["zh-Hans", "en"]
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
#### 不推荐方案
|
|
747
|
+
|
|
748
|
+
- ❌ 使用 `en/` 而非 `en_US/`(无法精确划分)
|
|
749
|
+
- ❌ base 和 en 的 key 不对应(运行时错误)
|
|
750
|
+
- ❌ 过度使用动态获取(性能问题)
|
|
751
|
+
- ❌ 实现复杂的动态语言切换(除非必需)
|
|
752
|
+
|
|
753
|
+
---
|
|
754
|
+
|
|
755
|
+
### 代码仓选择结论
|
|
756
|
+
|
|
757
|
+
**选择**:纯静态方案 + `en_US/` 目录
|
|
758
|
+
|
|
759
|
+
**核心原因**:
|
|
760
|
+
|
|
761
|
+
1. **简单可靠**
|
|
762
|
+
- ✅ 无需维护复杂的状态管理
|
|
763
|
+
- ✅ 自动跟随系统语言
|
|
764
|
+
- ✅ 代码量少,维护成本低
|
|
765
|
+
|
|
766
|
+
2. **性能最优**
|
|
767
|
+
- ✅ 编译时确定资源路径
|
|
768
|
+
- ✅ 无运行时语言切换开销
|
|
769
|
+
|
|
770
|
+
3. **需求匹配**
|
|
771
|
+
- ✅ 只需支持中英文
|
|
772
|
+
- ✅ 无应用内切换需求
|
|
773
|
+
- ✅ 精确区域划分(en_US)
|
|
774
|
+
|
|
775
|
+
**适用性**:✅ 该方案适用于 **大多数不需要应用内语言切换的应用**
|