@robsun/create-keystone-app 0.2.7 → 0.2.9

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.
Files changed (29) hide show
  1. package/dist/create-keystone-app.js +0 -0
  2. package/dist/create-module.js +0 -0
  3. package/package.json +7 -6
  4. package/template/.claude/skills/keystone-dev/SKILL.md +38 -13
  5. package/template/.claude/skills/keystone-dev/references/CAPABILITIES.md +80 -2
  6. package/template/.claude/skills/keystone-dev/references/TEMPLATES.md +220 -0
  7. package/template/.codex/skills/keystone-dev/SKILL.md +38 -13
  8. package/template/.codex/skills/keystone-dev/references/CAPABILITIES.md +80 -2
  9. package/template/.codex/skills/keystone-dev/references/TEMPLATES.md +220 -0
  10. package/template/apps/server/go.mod +1 -1
  11. package/template/apps/server/go.sum +1 -0
  12. package/template/apps/server/internal/modules/example/api/handler/item_handler.go +35 -32
  13. package/template/apps/server/internal/modules/example/domain/service/errors.go +13 -0
  14. package/template/apps/server/internal/modules/example/i18n/i18n.go +16 -0
  15. package/template/apps/server/internal/modules/example/i18n/keys.go +23 -0
  16. package/template/apps/server/internal/modules/example/i18n/locales/en-US.json +18 -0
  17. package/template/apps/server/internal/modules/example/i18n/locales/zh-CN.json +18 -0
  18. package/template/apps/server/internal/modules/example/module.go +9 -3
  19. package/template/apps/web/package.json +3 -1
  20. package/template/apps/web/src/app.config.ts +8 -1
  21. package/template/apps/web/src/modules/example/index.ts +7 -1
  22. package/template/apps/web/src/modules/example/locales/en-US/example.json +32 -0
  23. package/template/apps/web/src/modules/example/locales/zh-CN/example.json +32 -0
  24. package/template/apps/web/src/modules/example/pages/ExampleItemsPage.tsx +47 -45
  25. package/template/apps/web/src/modules/example/routes.tsx +6 -2
  26. package/template/docs/CONVENTIONS.md +73 -1
  27. package/template/docs/I18N.md +319 -0
  28. package/template/package.json +1 -0
  29. package/template/scripts/generate-i18n-types.js +154 -0
File without changes
File without changes
package/package.json CHANGED
@@ -1,6 +1,10 @@
1
- {
1
+ {
2
2
  "name": "@robsun/create-keystone-app",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
+ "scripts": {
5
+ "build": "node scripts/build.js",
6
+ "prepublishOnly": "node scripts/build.js && node scripts/prune-template-deps.js"
7
+ },
4
8
  "publishConfig": {
5
9
  "access": "public"
6
10
  },
@@ -15,8 +19,5 @@
15
19
  ],
16
20
  "engines": {
17
21
  "node": ">=18"
18
- },
19
- "scripts": {
20
- "build": "node scripts/build.js"
21
22
  }
22
- }
23
+ }
@@ -10,11 +10,26 @@ description: 基于 Keystone 平台开发业务模块。当用户需要创建新
10
10
  ## 工作流程
11
11
 
12
12
  1. **解析需求** → 识别所需能力
13
- 2. **生成前端模块** → routes.tsx, pages/, services/, types.ts
14
- 3. **生成后端模块** → handler/, service/, repository/, migrations/
15
- 4. **自动注册** → main.tsx + manifest.go + config.yaml
16
- 5. **输出调整建议**
17
- 6. **补测试并执行** → 见 references/testing.md
13
+ 2. **生成前端模块** → routes.tsx, pages/, services/, types.ts, locales/
14
+ 3. **生成后端模块** → handler/, service/, repository/, migrations/, i18n/
15
+ 4. **自动注册** → main.tsx + manifest.go + config.yaml
16
+ 5. **配置多语言** → 前端翻译文件 + 后端翻译键常量
17
+ 6. **输出调整建议**
18
+ 7. **补测试并执行** → 见 references/testing.md
19
+
20
+ ## 多语言最佳实践
21
+
22
+ **前端**:
23
+ - 所有用户可见文本必须使用 `t()` 翻译函数
24
+ - 翻译键使用点记法:`{module}:{section}.{key}`
25
+ - 避免硬编码文本,确保国际化覆盖率 100%
26
+
27
+ **后端**:
28
+ - 错误消息使用翻译键常量(keys.go)
29
+ - API 响应消息根据请求语言返回
30
+ - 使用 `i18n.T(c, key)` 获取翻译文本
31
+
32
+ 详见 [docs/I18N.md](../../docs/I18N.md)。
18
33
 
19
34
  ## 能力选择矩阵
20
35
 
@@ -27,13 +42,13 @@ description: 基于 Keystone 平台开发业务模块。当用户需要创建新
27
42
  | 导入、批量 | DataImporter | ImportHandler + Job队列 |
28
43
  | 导出、下载 | DataExporter | ExportHandler + Job队列 |
29
44
  | 上传、附件 | FileUpload | UploadHandler + 存储服务 |
30
- | 审批、流程 | ApprovalFlowEditor | 审批引擎 |
31
- | 权限 | PermissionGuard | 权限中间件 |
32
-
33
- 审批流程与接入说明见 [references/approval.md](references/approval.md)。
34
- 测试清单见 [references/testing.md](references/testing.md)。
35
- 详细能力清单见 [references/CAPABILITIES.md](references/CAPABILITIES.md)。
36
- 代码模板见 [references/TEMPLATES.md](references/TEMPLATES.md)。
45
+ | 审批、流程 | ApprovalFlowEditor | 审批引擎 |
46
+ | 权限 | PermissionGuard | 权限中间件 |
47
+
48
+ 审批流程与接入说明见 [references/approval.md](references/approval.md)。
49
+ 测试清单见 [references/testing.md](references/testing.md)。
50
+ 详细能力清单见 [references/CAPABILITIES.md](references/CAPABILITIES.md)。
51
+ 代码模板见 [references/TEMPLATES.md](references/TEMPLATES.md)。
37
52
 
38
53
  ## 模块结构约定
39
54
 
@@ -48,7 +63,11 @@ apps/web/src/modules/{name}/
48
63
  │ └── Form.tsx # ProForm
49
64
  ├── services/api.ts
50
65
  ├── types.ts
51
- └── help/index.md
66
+ ├── locales/ # 多语言翻译
67
+ │ ├── zh-CN/{module}.json
68
+ │ └── en-US/{module}.json
69
+ └── help/
70
+ └── index.md
52
71
  ```
53
72
 
54
73
  ### 后端模块
@@ -59,6 +78,12 @@ apps/server/internal/modules/{name}/
59
78
  ├── domain/models/
60
79
  ├── domain/service/
61
80
  ├── infra/repository/
81
+ ├── i18n/ # 多语言翻译
82
+ │ ├── i18n.go
83
+ │ ├── keys.go
84
+ │ └── locales/
85
+ │ ├── zh-CN.json
86
+ │ └── en-US.json
62
87
  └── bootstrap/migrations/
63
88
  ```
64
89
 
@@ -69,12 +69,46 @@ import { listNotifications, markNotificationRead, fetchUnreadCount } from '@robs
69
69
  import { getJob, listJobs } from '@robsun/keystone-web-core'
70
70
  ```
71
71
 
72
- ### 8. Hooks
72
+ ### 8. 多语言 (i18n)
73
+ ```typescript
74
+ // 翻译 Hook
75
+ import { useTranslation } from 'react-i18next'
76
+
77
+ // 使用示例
78
+ const { t } = useTranslation()
79
+ const title = t('module:key') // 命名空间:键
80
+ const description = t('common:actions.save')
81
+
82
+ // 平台多语言配置
83
+ import { getKeystoneConfig } from '@robsun/keystone-web-core'
84
+ const locale = getKeystoneConfig().ui?.i18n?.defaultLocale // 'zh-CN' | 'en-US'
85
+
86
+ // dayjs 本地化同步(自动完成)
87
+ import dayjs from 'dayjs'
88
+ dayjs.locale(getKeystoneConfig().ui?.locale?.dayjs ?? 'zh-cn')
89
+ ```
90
+
91
+ **翻译文件组织**:
92
+ ```
93
+ src/modules/{module}/locales/
94
+ ├── zh-CN/
95
+ │ └── {namespace}.json
96
+ └── en-US/
97
+ └── {namespace}.json
98
+ ```
99
+
100
+ **命名空间约定**:
101
+ - `common` - 通用文案(按钮、操作、状态等)
102
+ - `auth` - 认证相关
103
+ - `system` - 系统管理
104
+ - `{module}` - 业务模块专属翻译
105
+
106
+ ### 9. Hooks
73
107
  ```typescript
74
108
  import { useListState } from '@robsun/keystone-web-core'
75
109
  ```
76
110
 
77
- ### 9. 类型
111
+ ### 10. 类型
78
112
  ```typescript
79
113
  import type { ApiResponse, PaginatedData, PaginatedResponse } from '@robsun/keystone-web-core'
80
114
  import type { Permission, ModuleName, Action } from '@robsun/keystone-web-core'
@@ -126,3 +160,47 @@ storageService.Upload(...)
126
160
  storageService.Download(...)
127
161
  storageService.Delete(...)
128
162
  ```
163
+
164
+ ### 7. 多语言 (i18n)
165
+ ```go
166
+ // 获取当前请求语言环境
167
+ import "github.com/robsuncn/keystone/infra/i18n"
168
+
169
+ locale := i18n.GetLocale(c) // 从请求头或参数获取
170
+
171
+ // 翻译函数
172
+ i18n.T(c, "module.key") // 基础翻译
173
+ i18n.T(c, "module.greeting", "name", "张三") // 带变量
174
+ i18n.Tf(c, "module.count", count) // 复数形式
175
+
176
+ // 错误消息翻译
177
+ return errors.New(i18n.T(c, "module.errors.notFound"))
178
+ ```
179
+
180
+ **翻译文件组织**:
181
+ ```
182
+ internal/modules/{module}/i18n/
183
+ ├── i18n.go # 初始化
184
+ ├── keys.go # 翻译键常量
185
+ └── locales/
186
+ ├── zh-CN.json
187
+ └── en-US.json
188
+ ```
189
+
190
+ **翻译键常量定义**:
191
+ ```go
192
+ package i18n
193
+
194
+ const (
195
+ KeyItemCreated = "example.item.created"
196
+ KeyItemNotFound = "example.item.notFound"
197
+ KeyItemInvalid = "example.item.invalid"
198
+ )
199
+ ```
200
+
201
+ **模块初始化**:
202
+ ```go
203
+ func init() {
204
+ i18n.MustLoadModuleTranslations("example", Translations)
205
+ }
206
+ ```
@@ -157,6 +157,111 @@ export interface {Entity} {
157
157
  }
158
158
  ```
159
159
 
160
+ ### i18n 翻译文件
161
+
162
+ **locales/zh-CN/{module}.json**
163
+ ```json
164
+ {
165
+ "title": "{模块标题}",
166
+ "list": {
167
+ "title": "{实体}列表",
168
+ "empty": "暂无数据",
169
+ "columns": {
170
+ "name": "名称",
171
+ "status": "状态",
172
+ "createdAt": "创建时间"
173
+ }
174
+ },
175
+ "form": {
176
+ "create": "创建{实体}",
177
+ "edit": "编辑{实体}",
178
+ "fields": {
179
+ "name": "名称",
180
+ "description": "描述"
181
+ },
182
+ "placeholders": {
183
+ "name": "请输入名称"
184
+ }
185
+ },
186
+ "actions": {
187
+ "create": "新建",
188
+ "edit": "编辑",
189
+ "delete": "删除",
190
+ "save": "保存",
191
+ "cancel": "取消"
192
+ },
193
+ "messages": {
194
+ "createSuccess": "创建成功",
195
+ "updateSuccess": "更新成功",
196
+ "deleteSuccess": "删除成功",
197
+ "deleteConfirm": "确定要删除吗?"
198
+ }
199
+ }
200
+ ```
201
+
202
+ **locales/en-US/{module}.json**
203
+ ```json
204
+ {
205
+ "title": "{Module Title}",
206
+ "list": {
207
+ "title": "{Entity} List",
208
+ "empty": "No data",
209
+ "columns": {
210
+ "name": "Name",
211
+ "status": "Status",
212
+ "createdAt": "Created At"
213
+ }
214
+ },
215
+ "form": {
216
+ "create": "Create {Entity}",
217
+ "edit": "Edit {Entity}",
218
+ "fields": {
219
+ "name": "Name",
220
+ "description": "Description"
221
+ },
222
+ "placeholders": {
223
+ "name": "Enter name"
224
+ }
225
+ },
226
+ "actions": {
227
+ "create": "Create",
228
+ "edit": "Edit",
229
+ "delete": "Delete",
230
+ "save": "Save",
231
+ "cancel": "Cancel"
232
+ },
233
+ "messages": {
234
+ "createSuccess": "Created successfully",
235
+ "updateSuccess": "Updated successfully",
236
+ "deleteSuccess": "Deleted successfully",
237
+ "deleteConfirm": "Are you sure to delete?"
238
+ }
239
+ }
240
+ ```
241
+
242
+ ### 使用翻译的 List.tsx
243
+ ```tsx
244
+ import { useTranslation } from 'react-i18next'
245
+ import { ProTable } from '@robsun/keystone-web-core'
246
+
247
+ export function Component() {
248
+ const { t } = useTranslation() // 自动使用当前模块的命名空间
249
+
250
+ const columns = [
251
+ { title: t('{module}:list.columns.name'), dataIndex: 'name' },
252
+ { title: t('{module}:list.columns.status'), dataIndex: 'status' },
253
+ { title: t('{module}:list.columns.createdAt'), dataIndex: 'createdAt' },
254
+ ]
255
+
256
+ return (
257
+ <ProTable
258
+ columns={columns}
259
+ // ...
260
+ />
261
+ )
262
+ }
263
+ ```
264
+
160
265
  ## 后端模板
161
266
 
162
267
  ### module.go
@@ -310,3 +415,118 @@ func (r *Repository) Delete(ctx context.Context, id string) error {
310
415
  return r.db.Delete(&models.{Entity}{}, "id = ?", id).Error
311
416
  }
312
417
  ```
418
+
419
+ ### i18n/i18n.go
420
+ ```go
421
+ package i18n
422
+
423
+ import (
424
+ "embed"
425
+ "github.com/robsuncn/keystone/infra/i18n"
426
+ )
427
+
428
+ //go:embed locales/*.json
429
+ var Translations embed.FS
430
+
431
+ func init() {
432
+ // 注册模块翻译文件
433
+ i18n.MustLoadModuleTranslations("{module}", Translations)
434
+ }
435
+ ```
436
+
437
+ ### i18n/keys.go
438
+ ```go
439
+ package i18n
440
+
441
+ // 翻译键常量定义
442
+ const (
443
+ // 成功消息
444
+ KeyItemCreated = "{module}.item.created"
445
+ KeyItemUpdated = "{module}.item.updated"
446
+ KeyItemDeleted = "{module}.item.deleted"
447
+
448
+ // 错误消息
449
+ KeyItemNotFound = "{module}.item.notFound"
450
+ KeyItemInvalid = "{module}.item.invalid"
451
+ KeyItemAlreadyExists = "{module}.item.alreadyExists"
452
+
453
+ // 验证消息
454
+ KeyNameRequired = "{module}.validation.nameRequired"
455
+ KeyNameTooLong = "{module}.validation.nameTooLong"
456
+ )
457
+ ```
458
+
459
+ ### i18n/locales/zh-CN.json
460
+ ```json
461
+ {
462
+ "{module}": {
463
+ "item": {
464
+ "created": "{实体}创建成功",
465
+ "updated": "{实体}更新成功",
466
+ "deleted": "{实体}删除成功",
467
+ "notFound": "{实体}不存在",
468
+ "invalid": "{实体}数据无效",
469
+ "alreadyExists": "{实体}已存在"
470
+ },
471
+ "validation": {
472
+ "nameRequired": "名称不能为空",
473
+ "nameTooLong": "名称长度不能超过 {{max}} 个字符"
474
+ }
475
+ }
476
+ }
477
+ ```
478
+
479
+ ### i18n/locales/en-US.json
480
+ ```json
481
+ {
482
+ "{module}": {
483
+ "item": {
484
+ "created": "{Entity} created successfully",
485
+ "updated": "{Entity} updated successfully",
486
+ "deleted": "{Entity} deleted successfully",
487
+ "notFound": "{Entity} not found",
488
+ "invalid": "Invalid {entity} data",
489
+ "alreadyExists": "{Entity} already exists"
490
+ },
491
+ "validation": {
492
+ "nameRequired": "Name is required",
493
+ "nameTooLong": "Name cannot exceed {{max}} characters"
494
+ }
495
+ }
496
+ }
497
+ ```
498
+
499
+ ### 使用翻译的 service.go
500
+ ```go
501
+ package service
502
+
503
+ import (
504
+ "errors"
505
+ "github.com/gin-gonic/gin"
506
+ "github.com/robsuncn/keystone/infra/i18n"
507
+ modulei18n "app/internal/modules/{module}/i18n"
508
+ )
509
+
510
+ func (s *Service) Get(c *gin.Context, id string) (*models.{Entity}, error) {
511
+ item, err := s.repo.Get(c, id)
512
+ if err != nil {
513
+ // 使用翻译键返回错误
514
+ return nil, errors.New(i18n.T(c, modulei18n.KeyItemNotFound))
515
+ }
516
+ return item, nil
517
+ }
518
+
519
+ func (s *Service) Create(c *gin.Context, entity *models.{Entity}) error {
520
+ if entity.Name == "" {
521
+ return errors.New(i18n.T(c, modulei18n.KeyNameRequired))
522
+ }
523
+
524
+ err := s.repo.Create(c, entity)
525
+ if err != nil {
526
+ return err
527
+ }
528
+
529
+ // 可以在日志或审计中使用翻译消息
530
+ return nil
531
+ }
532
+ ```
@@ -10,11 +10,26 @@ description: 基于 Keystone 平台开发业务模块。当用户需要创建新
10
10
  ## 工作流程
11
11
 
12
12
  1. **解析需求** → 识别所需能力
13
- 2. **生成前端模块** → routes.tsx, pages/, services/, types.ts
14
- 3. **生成后端模块** → handler/, service/, repository/, migrations/
15
- 4. **自动注册** → main.tsx + manifest.go + config.yaml
16
- 5. **输出调整建议**
17
- 6. **补测试并执行** → 见 references/testing.md
13
+ 2. **生成前端模块** → routes.tsx, pages/, services/, types.ts, locales/
14
+ 3. **生成后端模块** → handler/, service/, repository/, migrations/, i18n/
15
+ 4. **自动注册** → main.tsx + manifest.go + config.yaml
16
+ 5. **配置多语言** → 前端翻译文件 + 后端翻译键常量
17
+ 6. **输出调整建议**
18
+ 7. **补测试并执行** → 见 references/testing.md
19
+
20
+ ## 多语言最佳实践
21
+
22
+ **前端**:
23
+ - 所有用户可见文本必须使用 `t()` 翻译函数
24
+ - 翻译键使用点记法:`{module}:{section}.{key}`
25
+ - 避免硬编码文本,确保国际化覆盖率 100%
26
+
27
+ **后端**:
28
+ - 错误消息使用翻译键常量(keys.go)
29
+ - API 响应消息根据请求语言返回
30
+ - 使用 `i18n.T(c, key)` 获取翻译文本
31
+
32
+ 详见 [docs/I18N.md](../../docs/I18N.md)。
18
33
 
19
34
  ## 能力选择矩阵
20
35
 
@@ -27,13 +42,13 @@ description: 基于 Keystone 平台开发业务模块。当用户需要创建新
27
42
  | 导入、批量 | DataImporter | ImportHandler + Job队列 |
28
43
  | 导出、下载 | DataExporter | ExportHandler + Job队列 |
29
44
  | 上传、附件 | FileUpload | UploadHandler + 存储服务 |
30
- | 审批、流程 | ApprovalFlowEditor | 审批引擎 |
31
- | 权限 | PermissionGuard | 权限中间件 |
32
-
33
- 审批流程与接入说明见 [references/approval.md](references/approval.md)。
34
- 测试清单见 [references/testing.md](references/testing.md)。
35
- 详细能力清单见 [references/CAPABILITIES.md](references/CAPABILITIES.md)。
36
- 代码模板见 [references/TEMPLATES.md](references/TEMPLATES.md)。
45
+ | 审批、流程 | ApprovalFlowEditor | 审批引擎 |
46
+ | 权限 | PermissionGuard | 权限中间件 |
47
+
48
+ 审批流程与接入说明见 [references/approval.md](references/approval.md)。
49
+ 测试清单见 [references/testing.md](references/testing.md)。
50
+ 详细能力清单见 [references/CAPABILITIES.md](references/CAPABILITIES.md)。
51
+ 代码模板见 [references/TEMPLATES.md](references/TEMPLATES.md)。
37
52
 
38
53
  ## 模块结构约定
39
54
 
@@ -48,7 +63,11 @@ apps/web/src/modules/{name}/
48
63
  │ └── Form.tsx # ProForm
49
64
  ├── services/api.ts
50
65
  ├── types.ts
51
- └── help/index.md
66
+ ├── locales/ # 多语言翻译
67
+ │ ├── zh-CN/{module}.json
68
+ │ └── en-US/{module}.json
69
+ └── help/
70
+ └── index.md
52
71
  ```
53
72
 
54
73
  ### 后端模块
@@ -59,6 +78,12 @@ apps/server/internal/modules/{name}/
59
78
  ├── domain/models/
60
79
  ├── domain/service/
61
80
  ├── infra/repository/
81
+ ├── i18n/ # 多语言翻译
82
+ │ ├── i18n.go
83
+ │ ├── keys.go
84
+ │ └── locales/
85
+ │ ├── zh-CN.json
86
+ │ └── en-US.json
62
87
  └── bootstrap/migrations/
63
88
  ```
64
89
 
@@ -69,12 +69,46 @@ import { listNotifications, markNotificationRead, fetchUnreadCount } from '@robs
69
69
  import { getJob, listJobs } from '@robsun/keystone-web-core'
70
70
  ```
71
71
 
72
- ### 8. Hooks
72
+ ### 8. 多语言 (i18n)
73
+ ```typescript
74
+ // 翻译 Hook
75
+ import { useTranslation } from 'react-i18next'
76
+
77
+ // 使用示例
78
+ const { t } = useTranslation()
79
+ const title = t('module:key') // 命名空间:键
80
+ const description = t('common:actions.save')
81
+
82
+ // 平台多语言配置
83
+ import { getKeystoneConfig } from '@robsun/keystone-web-core'
84
+ const locale = getKeystoneConfig().ui?.i18n?.defaultLocale // 'zh-CN' | 'en-US'
85
+
86
+ // dayjs 本地化同步(自动完成)
87
+ import dayjs from 'dayjs'
88
+ dayjs.locale(getKeystoneConfig().ui?.locale?.dayjs ?? 'zh-cn')
89
+ ```
90
+
91
+ **翻译文件组织**:
92
+ ```
93
+ src/modules/{module}/locales/
94
+ ├── zh-CN/
95
+ │ └── {namespace}.json
96
+ └── en-US/
97
+ └── {namespace}.json
98
+ ```
99
+
100
+ **命名空间约定**:
101
+ - `common` - 通用文案(按钮、操作、状态等)
102
+ - `auth` - 认证相关
103
+ - `system` - 系统管理
104
+ - `{module}` - 业务模块专属翻译
105
+
106
+ ### 9. Hooks
73
107
  ```typescript
74
108
  import { useListState } from '@robsun/keystone-web-core'
75
109
  ```
76
110
 
77
- ### 9. 类型
111
+ ### 10. 类型
78
112
  ```typescript
79
113
  import type { ApiResponse, PaginatedData, PaginatedResponse } from '@robsun/keystone-web-core'
80
114
  import type { Permission, ModuleName, Action } from '@robsun/keystone-web-core'
@@ -126,3 +160,47 @@ storageService.Upload(...)
126
160
  storageService.Download(...)
127
161
  storageService.Delete(...)
128
162
  ```
163
+
164
+ ### 7. 多语言 (i18n)
165
+ ```go
166
+ // 获取当前请求语言环境
167
+ import "github.com/robsuncn/keystone/infra/i18n"
168
+
169
+ locale := i18n.GetLocale(c) // 从请求头或参数获取
170
+
171
+ // 翻译函数
172
+ i18n.T(c, "module.key") // 基础翻译
173
+ i18n.T(c, "module.greeting", "name", "张三") // 带变量
174
+ i18n.Tf(c, "module.count", count) // 复数形式
175
+
176
+ // 错误消息翻译
177
+ return errors.New(i18n.T(c, "module.errors.notFound"))
178
+ ```
179
+
180
+ **翻译文件组织**:
181
+ ```
182
+ internal/modules/{module}/i18n/
183
+ ├── i18n.go # 初始化
184
+ ├── keys.go # 翻译键常量
185
+ └── locales/
186
+ ├── zh-CN.json
187
+ └── en-US.json
188
+ ```
189
+
190
+ **翻译键常量定义**:
191
+ ```go
192
+ package i18n
193
+
194
+ const (
195
+ KeyItemCreated = "example.item.created"
196
+ KeyItemNotFound = "example.item.notFound"
197
+ KeyItemInvalid = "example.item.invalid"
198
+ )
199
+ ```
200
+
201
+ **模块初始化**:
202
+ ```go
203
+ func init() {
204
+ i18n.MustLoadModuleTranslations("example", Translations)
205
+ }
206
+ ```