命名空间规划与 key 命名规范
High Contrast
Dark Mode
Light Mode
Sepia
Forest
2 min read428 words

命名空间规划与 key 命名规范

核心问题:翻译 key 该如何命名?按什么维度划分 namespace?如何避免 key 越来越混乱难以维护?


真实场景

你的项目运行了 2 年,翻译文件里出现了 btn_savesaveButtonsave_btn_textcommon_save 四个意思相同的 key,还有大量 text_001label_xyz 这样无法理解含义的 key。这就是缺乏规范的后果。


Namespace 规划原则

按功能模块划分(推荐)

locales/zh-CN/
├── common.json          # 全局通用(按钮、状态、导航)
├── auth.json            # 认证(登录、注册、找回密码)
├── product.json         # 商品(列表、详情、搜索)
├── cart.json            # 购物车
├── checkout.json        # 结算流程
├── order.json           # 订单管理
├── account.json         # 账户设置
├── review.json          # 评价
├── errors.json          # 错误信息(独立文件便于后端复用)
└── admin/
├── dashboard.json   # 管理后台
└── products.json    # 商品管理

划分原则: - 每个 namespace 对应一个功能域,不跨域 - common 只放真正全局复用的文字 - 按路由或页面粒度可以,但不要太细(避免 namespace 碎片化) - 后台模块单独放一个子目录

按路由划分(简单项目)

locales/
└── zh-CN/
├── common.json
├── pages/
│   ├── home.json
│   ├── product-detail.json
│   └── checkout.json
└── components/
├── header.json
└── footer.json

Key 命名规范

基本原则

1. 语义化:key 描述内容含义,不描述位置或样式
2. 层次化:用点号(.)分隔层级,3 层以内
3. 一致性:同类文字用相同的前缀模式
4. 稳定性:key 一旦确定不轻易改名(会破坏翻译)

命名规范示例

// common.json
{
// ✅ 按动作类型分组
"actions": {
"save": "保存",
"cancel": "取消",
"confirm": "确认",
"delete": "删除",
"edit": "编辑",
"view": "查看",
"back": "返回",
"next": "下一步",
"submit": "提交",
"retry": "重试",
"search": "搜索",
"filter": "筛选",
"sort": "排序",
"export": "导出",
"import": "导入"
},
// ✅ 状态分组
"status": {
"loading": "加载中...",
"empty": "暂无数据",
"error": "加载失败",
"success": "操作成功",
"noResults": "没有找到相关结果"
},
// ✅ 通用标签
"labels": {
"required": "必填",
"optional": "选填",
"new": "新",
"hot": "热门",
"recommended": "推荐"
},
// ✅ 导航
"nav": {
"home": "首页",
"products": "商品",
"cart": "购物车",
"account": "我的"
}
}
// product.json
{
// ✅ 按子功能分组
"listing": {
"title": "商品列表",
"noProducts": "暂无商品",
"sortBy": "排序方式",
"sortOptions": {
"priceAsc": "价格从低到高",
"priceDesc": "价格从高到低",
"newest": "最新上架",
"sales": "销量优先"
}
},
"detail": {
"title": "商品详情",
"description": "商品描述",
"specifications": "规格参数",
"reviews": "用户评价",
"relatedProducts": "相关推荐",
"addToCart": "加入购物车",
"buyNow": "立即购买",
"outOfStock": "暂时缺货",
"stock": "库存:{count} 件",
"sku": "规格选择",
"quantity": "购买数量"
},
"price": {
"label": "价格",
"original": "原价",
"sale": "促销价",
"discount": "折扣",
"freeShipping": "包邮",
"shippingFee": "运费:{amount}"
}
}

反模式:不该这样命名

// ❌ 常见的坏习惯
{
// 描述位置而非语义
"topRightButton": "确认",
"leftSideLabel": "用户名",
// 序号命名
"text_001": "欢迎",
"text_002": "登录",
"label_xyz": "邮箱",
// 过于冗余
"common_button_save_text": "保存",
// 混合大小写/下划线
"saveButton": "保存",
"save_button": "保存",
"SaveButton": "保存",
// 英文缩写无法理解
"btn_sv": "保存",
"lbl_usr": "用户"
}

处理复杂 Key 场景

动态内容(占位符)

{
// ✅ 占位符用驼峰命名,加花括号
"greeting": "你好,{userName}!",
"orderStatus": "订单 {orderId} 状态:{status}",
"fileSize": "文件大小:{size}",
// 带 ICU 格式的复杂占位符
"cartSummary": "{count, plural, =0 {购物车是空的} other {共 # 件,合计 {total}}}",
// 日期占位符(由框架处理格式化)
"createdAt": "创建于 {date, date, short}",
"expiresAt": "有效期至 {date, date, long}"
}

相似但不完全相同的文字

{
// ❌ 错误:共用同一个 key,翻译不同语言时出问题
// "save" 在"保存草稿"和"保存设置"的语境可能不同
// ✅ 正确:区分语境
"actions": {
"saveDraft": "保存草稿",
"saveSettings": "保存设置",
"saveAndPublish": "保存并发布"
}
}

富文本(HTML 嵌入)

{
// ✅ 使用 ICU 标签语法(框架处理 HTML 注入)
"termsAgreement": "点击即表示您同意<link>服务条款</link>和<privacy>隐私政策</privacy>",
"welcomeMessage": "欢迎回来,<bold>{name}</bold>!",
// ❌ 不要在翻译文件里写 HTML(XSS 风险,且难以维护)
"danger": "点击 <a href='/terms'>服务条款</a> 同意"
}

翻译 key 的生命周期管理

Key 的变更策略

stateDiagram-v2 [*] --> Active: 创建 key Active --> Deprecated: 标记废弃(保留翻译) Deprecated --> Removed: 确认无使用后删除 Active --> Renamed: 重命名(需迁移) Renamed --> Active: 迁移完成
// 废弃的 key 添加注释(JSONC 格式)
{
// @deprecated: 使用 actions.save 代替,将在 v3.0 删除
"save_text": "保存",
"actions": {
"save": "保存"
}
}

版本化翻译 key(大规模重构时)

{
// 重大改版时,新旧 key 并存,分批迁移
"v2": {
"checkout": {
"title": "确认订单"
}
},
// 旧版 key(待迁移)
"checkout_title": "确认订单"
}

命名规范文档模板

建议在项目根目录维护 I18N_GUIDE.md

# i18n 翻译 Key 命名规范
## Namespace 划分
| Namespace | 文件 | 描述 |
|-----------|------|------|
| common | common.json | 全局通用(按钮、状态、标签、导航) |
| auth | auth.json | 认证流程 |
| product | product.json | 商品相关 |
| cart | cart.json | 购物车 |
| checkout | checkout.json | 结算流程 |
| order | order.json | 订单管理 |
| errors | errors.json | 错误信息 |
## Key 命名规则
1. 使用点号分隔的层级结构,最多 3 层
2. 驼峰命名(camelCase)
3. 按语义而非位置命名
4. 占位符使用 `{camelCase}` 格式
## 常见分组前缀
| 前缀 | 用途 |
|------|------|
| `actions.*` | 操作按钮(save/cancel/confirm/delete)|
| `status.*` | 状态提示(loading/empty/error/success)|
| `labels.*` | 表单标签和说明文字 |
| `messages.*` | 提示信息和确认对话框 |
| `errors.*` | 错误提示 |
## 禁止的命名模式
- 位置描述:`topButton`、`leftLabel`
- 序号命名:`text001`、`label_xyz`
- 样式描述:`redText`、`bigTitle`
- HTML 内容:不要在 key 值中直接写 HTML 标签

IDE 工具支持

VS Code i18n Ally 插件

// .vscode/settings.json
{
"i18n-ally.localesPaths": ["src/locales"],
"i18n-ally.sourceLanguage": "zh-CN",
"i18n-ally.displayLanguage": "zh-CN",
"i18n-ally.keystyle": "nested",      // 嵌套 key 风格
"i18n-ally.namespace": true,         // 启用 namespace
"i18n-ally.pathMatcher": "{locale}/{namespace}.json",
// 翻译完成度警告阈值
"i18n-ally.annotations": true
}

i18n Ally 功能: - 在代码中内联显示翻译文字 - 高亮显示缺失翻译的 key - 右键直接提取字符串为翻译 key - 各语言翻译完成度统计


下一节:key 命名规范建立了,接下来解决如何自动检测缺失翻译,并在 CI 中拦截不完整的翻译提交。

Missing Key 检测与 CI 集成