i18n-locales-shared
v1.0.0
Published
Single source of truth for i18n keys (multi-frontend & multi-backend)
Readme
i18n-repo 独立仓库国际化技术方案(前后端通用)
1. 目标
建立 独立 i18n 仓库(Single Source of Truth),实现:
- 多前端、多后端 共用同一 Key 源,前后端统一 Key
- 多语言可扩展
- 通过 Key 前缀(应用/域) 避免多端 Key 冲突
- 可 CI 校验(Key 一致、占位符一致)
- 可版本化发布,多端可钉版本、分批升级
2. 总体架构
2.1 单源多端消费
frontend-web ─┐
frontend-admin ─┤
frontend-mobile ─┼── @company/i18n-locales (NPM / Git / CDN)
backend-user ─┤
backend-order ─┤
backend-payment ─┘
│
▼
i18n-repo(唯一 Key 源)- 多前端:共用同一 NPM 包,通过 Key 前缀(域) 区分应用,避免 Key 冲突。
- 多后端:共用同一 Key 源,API 统一返回
message_key,由前端或网关按语言解析;后端可不依赖 NPM 包,仅维护 Key 字符串常量或从 i18n-repo 同步定义。
3. 仓库结构规范
i18n-repo/
├── locales/
│ ├── en-US.json
│ ├── zh-CN.json
│ └── ja-JP.json
├── keys/
│ ├── frontend/ # 前端团队维护(仅前端展示用 Key)
│ │ ├── common.json
│ │ ├── explorer.json
│ │ ├── faucet.json
│ │ ├── dex.json
│ │ └── indexer.json
│ └── backend/ # 后端团队维护(仅后端返回用 Key)
│ ├── common.json
│ ├── explorer.json
│ ├── faucet.json
│ ├── dex.json
│ └── indexer.json
├── scripts/
│ ├── validate-keys.js
│ └── build.js
└── package.json- 域划分:业务域为 common、explorer、faucet、dex、indexer;
locales/*.json为单文件合并所有 Key。 - 前后端文件分离(避免冲突):同一域下前端只改
keys/frontend/<domain>.json,后端只改keys/backend/<domain>.json,互不编辑同一文件,避免合并冲突;看路径即可知道 Key 是给前端用还是后端用。同一 Key 只能出现在 frontend 或 backend 其一,不能重复。 - 多域引用:一个前端可以同时引用多个域(如 common + explorer + faucet),按需使用对应 Key;引入整包时所有 Key 在同一份 locale 中,使用时
t('common.ui.submit')、t('explorer.block.title')等混用即可。若需按域按需加载减小体积,可在 build 中按域产出多份 JSON 供前端分别引用。
4. Key 命名规范(防冲突核心)
4.1 命名规则(域 + 消费端 + 业务)
<domain>.<consumer>.<module>.<feature>.[<action>]<domain>:业务域,本项目为 common、explorer、faucet、dex、indexer。<consumer>(必选):从 Key 本身就能看出是前端还是后端定义,避免前后端误用同一 Key 或重复定义。- 前端:固定用
ui,表示前端展示用(如common.ui.login.title、explorer.ui.block.title)。 - 后端:用
error(错误码文案)、api(接口返回文案)等,表示后端返回用(如common.error.network、explorer.error.not_found)。
- 前端:固定用
4.2 示例
| 域 | 前端 Key(.ui.) | 后端 Key(.error. / .api.*) | | -- | ----------------- | ----------------------------- | | common | common.ui.login.title、common.ui.submit | common.error.network | | explorer | explorer.ui.block.title、explorer.ui.tx.detail | explorer.error.not_found(示例) | | faucet | faucet.ui.claim.title、faucet.ui.claim.success | — | | dex | dex.ui.swap.title、dex.ui.pool.add | — | | indexer | indexer.ui.status.title、indexer.ui.sync.pending | — |
4.3 规则
- 全小写
- 使用
.分层 - 域后紧跟消费端:前端统一
.<domain>.ui.*,后端统一.<domain>.error.*或.<domain>.api.*,看 Key 即知归属 - 禁止硬编码文案
- 禁止重复 Key(同一 Key 字符串只能出现一次)
5. 文案文件格式规范
5.1 占位参数(可选)
可以。 本地化翻译中支持占位参数,格式为 {参数名}(如 {name}、{code}、{count})。同一 Key 在各语言中的参数名必须一致,仅文案内容可不同。
示例(locales):
"common.ui.welcome": "欢迎,{name}",
"common.error.with_code": "错误码:{code}"- 前端:传入变量替换占位符。例如 i18next:
t('common.ui.welcome', { name: '张三' })→ 「欢迎,张三」。 - 后端:API 返回
message_key+params,由前端或网关做替换。例如{ "message_key": "common.ui.welcome", "params": { "name": "张三" } }。
CI 校验时建议检查:同一 Key 在各语言中的占位符集合一致(如 zh 有 {name} 则 en、ja 也须有 {name})。
locales/zh-CN.json
{
"common.ui.login.title": "登录",
"common.ui.submit": "提交",
"common.error.network": "网络错误",
"explorer.ui.block.title": "区块",
"explorer.ui.tx.detail": "交易详情",
"faucet.ui.claim.title": "领取",
"faucet.ui.claim.success": "领取成功",
"dex.ui.swap.title": "兑换",
"dex.ui.pool.add": "添加流动性",
"indexer.ui.status.title": "索引状态",
"indexer.ui.sync.pending": "同步中"
}locales/en-US.json
{
"common.ui.login.title": "Login",
"common.ui.submit": "Submit",
"common.error.network": "Network error",
"explorer.ui.block.title": "Block",
"explorer.ui.tx.detail": "Transaction detail",
"faucet.ui.claim.title": "Claim",
"faucet.ui.claim.success": "Claim succeeded",
"dex.ui.swap.title": "Swap",
"dex.ui.pool.add": "Add liquidity",
"indexer.ui.status.title": "Indexer status",
"indexer.ui.sync.pending": "Syncing"
}6. 前端接入(React / Vue 通用)
6.1 安装依赖
npm install @company/i18n-locales i18next6.2 初始化 i18n
import zh from '@company/i18n-locales/zh-CN.json'
import en from '@company/i18n-locales/en-US.json'
const resources = {
zh: { translation: zh },
en: { translation: en }
}6.3 使用 Key(按域,前端用 .ui.*)
t('common.ui.login.title')
t('common.ui.submit')
t('explorer.ui.block.title')
t('faucet.ui.claim.success')6.4 一个前端引用多个域
一个前端可以同时使用多个域的 Key(common、explorer、faucet、dex、indexer 等)。引入整包时所有 Key 已在一份 locale 中,无需按文件拆分引用;前端只使用带 .ui. 的 Key,按域混用即可,例如:
// 同一页面可混用 common、explorer、faucet 等(均为 .ui.* 前端 Key)
t('common.ui.submit')
t('explorer.ui.tx.detail')
t('faucet.ui.claim.title')若希望按域按需加载以减小包体积,可在本仓库的 scripts/build.js 中按域产出多份 JSON(如 dist/common/zh-CN.json、dist/explorer/zh-CN.json),前端按需引用对应文件。
7. 后端接入(Key 模式推荐)
7.1 API 返回 Key(推荐,多后端通用)
各后端服务不依赖 NPM 包,仅在响应中返回 message_key(及可选 params),由前端或网关根据请求语言解析文案。
{
"code": 10004,
"message_key": "error.user.not_found",
"params": { "userId": "123" }
}7.2 多后端实现方式
- 常量/枚举:从 i18n-repo 同步或手写 Key 常量,避免拼写错误。
- CI 同步:可选脚本从 i18n-repo 生成各语言的 Key 列表或代码常量,供各后端仓库引用。
7.3 Go 示例
return Error("error.user.not_found")8. Key 新增 / 修改流程(变更规范)
8.1 新增 Key
- 确定归属:前端用 → 在
keys/frontend/<domain>.json添加;后端用 → 在keys/backend/<domain>.json添加(同一 Key 只能归属一端)。 - 在所有
locales/*.json添加翻译。 - 提交 PR。
- CI 校验 Key(含前后端 Key 无交叉、keys 与 locales 一致)。
8.2 修改文案(不影响 Key)
- 仅更新
locales/*.json - 发布 patch 版本
8.3 废弃 Key
- 标记 deprecated
- 两个版本后移除
9. CI 校验规则(防 Key 漏失)
校验内容
- 各语言 Key 是否一致(zh-CN、en-US、ja-JP 等所有 locales 同 Key 集)
- keys/frontend 与 keys/backend 的 Key 无交叉:同一 Key 只能出现在 frontend 或 backend 其一,避免归属不清
- keys 并集与 locales 的 Key 一致:keys 中定义的 Key 须在 locales 中存在,locales 中的 Key 须在 keys 中有归属
- 参数占位符是否一致(如
{name}在各语言中一致)
validate-keys.js 行为
- 收集
keys/frontend/*.json与keys/backend/*.json中所有 Key - 校验无 Key 同时出现在 frontend 与 backend
- 校验各 locale 文件 Key 一致
- 校验 keys 并集与 locales Key 集一致
10. Code 长度与 Key 规模规范
推荐长度
| 项目 | 推荐 | | --------- | -------- | | Key 长度 | 20–60 字符 | | 单文件 Key 数 | < 1000 | | 命名层级 | 3–5 层 |
11. 冲突防护策略
命名空间隔离(域 + 消费端,看 Key 即知归属)
- 前端 Key:
<domain>.ui.*(如 common.ui.、explorer.ui.),看 Key 即知是前端定义。 - 后端 Key:
<domain>.error.*、<domain>.api.*(如 common.error.、explorer.error.),看 Key 即知是后端定义。
common.ui.* common.error.*
explorer.ui.* explorer.error.*
faucet.ui.* faucet.error.*
dex.ui.* dex.error.*
indexer.ui.* indexer.error.*Key 归属(前后端文件分离,避免同文件冲突)
| 路径 | 维护方 | 说明 | | ---- | ------ | ---- | | keys/frontend/.json | 前端 | 仅前端展示用 Key(UI 文案、前端提示等);看路径即知归属前端 | | keys/backend/.json | 后端 | 仅后端返回用 Key(API 错误码文案、后端提示等);看路径即知归属后端 |
同一域(如 explorer)下:前端只改 keys/frontend/explorer.json,后端只改 keys/backend/explorer.json,互不编辑同一文件,避免冲突。同一 Key 只能出现在 frontend 或 backend 其一。
域 Ownership(业务归属)
| 域 | 说明 | | -- | ---- | | common | 通用 UI / 错误等 | | explorer | Explorer 相关 | | faucet | Faucet 相关 | | dex | DEX 相关 | | indexer | Indexer 相关 |
12. 发布与版本管理
版本规则(SemVer)
| 变更 | 版本 | | ------ | ----- | | 新增 Key | minor | | 修改文案 | patch | | 删除 Key | major |
发布流程
npm version minor
npm publishCDN 同步:
https://cdn.company.com/i18n/v1.4.0/zh-CN.json13. 多端消费与版本策略
13.1 多前端消费
| 策略 | 说明 |
| ---- | ---- |
| 统一包 | 所有前端依赖同一 NPM 包 @company/i18n-locales,按需使用各域 Key(common.、explorer.、faucet.* 等);一个前端可引用多个域,混用即可。 |
| 版本钉钉 | 各前端在 package.json 中钉住版本(如 ^1.4.0),升级时统一升级或按需升级;新增 Key 为 minor,各端可滞后升级。 |
| 按需加载(可选) | 若包体积敏感,可在 i18n-repo 的 build 中按域产出多份 JSON(如 common/zh-CN.json、explorer/zh-CN.json),前端按需引用多个域文件。 |
13.2 多后端消费
| 策略 | 说明 |
| ---- | ---- |
| 仅返回 Key | 推荐:API 只返回 message_key(及可选 params),由前端或网关根据语言解析;后端无需嵌入 NPM 包,仅维护 Key 常量或从 i18n-repo 同步。 |
| Key 同步 | 通过 CI 或脚本从 i18n-repo 同步 Key 列表到各后端仓库(如生成 Go/Java 常量),保证 Key 存在且拼写一致。 |
| 版本兼容 | 后端不依赖 NPM 版本;i18n-repo 删除/重命名 Key 时需走 major,并提前通知各后端下线旧 Key。 |
13.3 升级策略小结
- 前端:
npm install @company/i18n-locales@<version>,建议统一跟随 minor,各端可分批升级。 - 后端:以 Key 为契约,不强制跟版本;删除 Key 须发 major 并同步各服务。
14. 推荐团队协作流程
| 角色 | 职责 | | -- | ------ | | 产品 | 提供文案需求 | | 开发 | 添加 Key | | 翻译 | 补充语言 | | CI | 校验一致性 |
15. 最佳实践总结
- i18n 独立仓库,单源多端消费
- Key 唯一来源,多端通过 Key 前缀(应用/域) 分区,避免冲突
- 多前端:同一 NPM 包 + 域前缀(common.、explorer.、faucet.、dex.、indexer.*),一个前端可引用多个域;多后端:API 返回 message_key,前端/网关解析
- CI 自动防漂移(Key 一致、占位符一致)
- 语义化版本发布;多端可钉版本、分批升级
