--- trigger: always_on --- # 后端国际化(i18n)规范 ## 文件组织 每个业务模块在 `internal/{module}/imsg/` 目录下维护国际化消息: ``` internal/{module}/imsg/ ├── imsg.go # 消息ID常量定义(MsgId) ├── zh_cn.go # 中文语言包 └── en.go # 英文语言包 ``` ### imsg.go — 常量定义 ```go package imsg import ( "mayfly-go/internal/pkg/consts" "mayfly-go/pkg/i18n" ) func init() { i18n.AppendLangMsg(i18n.Zh_CN, Zh_CN) i18n.AppendLangMsg(i18n.En, En) } const ( LogDbSave = iota + consts.ImsgNumDb LogDbDelete ErrDbNameExist ) ``` ### zh_cn.go — 中文语言包 ```go package imsg import "mayfly-go/pkg/i18n" var Zh_CN = map[i18n.MsgId]string{ LogDbSave: "保存数据库配置", LogDbDelete: "删除数据库配置", ErrDbNameExist: "该实例下数据库名已存在", } ``` ### en.go — 英文语言包 ```go package imsg import "mayfly-go/pkg/i18n" var En = map[i18n.MsgId]string{ LogDbSave: "Save database configuration", LogDbDelete: "Delete database configuration", ErrDbNameExist: "The database name already exists in this instance", } ``` ## 消息ID编号规则 各模块起始编号定义在 `internal/pkg/consts/consts.go`,新增模块需注册唯一起始值: ```go const ( ImsgNumSys = 10000 ImsgNumAuth = 20000 ImsgNumDb = 60000 ImsgNumAi = 140000 // ... ) ``` 模块内使用 `iota + consts.ImsgNum{Xxx}` 自增,避免全局冲突。 ## 使用方式 ### 国际化业务错误 ```go return errorx.NewBizI(ctx, imsg.ErrDbNameExist) ``` ### 国际化操作日志 ```go req.NewPost("", d.Save).Log(req.NewLogSaveI(imsg.LogDbSave)) ``` ### 模板变量替换 ```go // 定义:ErrDbNotAccess = "未配置数据库【{{.dbName}}】的操作权限" errorx.NewBizI(ctx, imsg.ErrDbNotAccess, "dbName", dbName) // 或直接使用 i18n 包 i18n.T(imsg.DataSyncSuccessMsg, "count", 100) i18n.TC(ctx, imsg.DataSyncSuccessMsg, "count", 100) ``` ## 边界 - ✅ **Always**: 新增模块时必须同步创建 `imsg.go`、`zh_cn.go`、`en.go` 三个文件 - ✅ **Always**: 操作日志消息以 `Log` 开头,业务错误以 `Err` 开头 - 🚫 **Never**: 在 `errorx.NewBiz("硬编码中文")` 中直接使用硬编码文本,必须走国际化