国际化 i18n
「顿悟」使用 Minecraft 原生的 Component + lang 文件机制实现国际化。无论你是数据包作者还是模组开发者,只需在合适的 assets/<namespace>/lang/<语言>.json 中提供翻译键,就能让游戏自动显示本地化文本。
机制:Component 原生支持
数据包中所有 Component 类型的字段(name / description / condition_description / *_reward_description / UI 文本)都支持三种 JSON 写法:
| 写法 | 含义 |
|---|---|
"战士"(字符串) | 纯文本(literal) |
{ "text": "战士", "color": "gold" }(对象) | 带样式的纯文本 |
{ "translate": "mymod.module.combat.name" }(对象) | 翻译键(查 lang 文件) |
翻译键的工作方式
当 JSON 写为 {"translate": "key"} 时,Minecraft 在客户端自动查找该 key 对应的翻译:
- 在
assets/<namespace>/lang/zh_cn.json等语言文件中找到 → 显示翻译后的文本 - 找不到 → 显示原始 key 字符串
这一机制由 Minecraft 原生支持,Epiphany 不做额外处理。你只需要:① 在 JSON 中写 {"translate": "key"};② 在 lang 文件中提供该 key 的翻译。
Epiphany 数据包的缺省 lang 自动回退
TIP
当某个 Component 字段缺省(不写或写为 null)时,Epiphany 会自动构造一个约定翻译键,而不是直接显示 ID 字符串或留空。
这意味着你无需在 JSON 中写 {"translate": ...},只要在 lang 文件中填好约定键即可。
四个数据类型的回退规则:
<type>.<namespace>.<path>.<field>| 数据类型 | 字段 | 翻译键 |
|---|---|---|
| Module | name | module.<ns>.<path>.name |
| Module | description | module.<ns>.<path>.description |
| Module | condition_description | module.<ns>.<path>.condition_description |
| Module | on_select_reward_description | module.<ns>.<path>.on_select_reward_description |
| Module | on_complete_reward_description | module.<ns>.<path>.on_complete_reward_description |
| Insight | name | insight.<ns>.<path>.name |
| Insight | description | insight.<ns>.<path>.description |
| Insight | reward_description | insight.<ns>.<path>.reward_description |
| Epiphany | name | epiphany.<ns>.<path>.name |
| Epiphany | description | epiphany.<ns>.<path>.description |
| Epiphany | condition_description | epiphany.<ns>.<path>.condition_description |
| Epiphany | reward_description | epiphany.<ns>.<path>.reward_description |
| Path | name | path.<ns>.<path>.name |
| Path | description | path.<ns>.<path>.description |
其中 <ns> 与 <path> 来自注册 ID <ns>:<path>。如:
data/mymod/epiphany/module/class/warrior.json→ 注册 IDmymod:class/warriorname缺省时回退键 →module.mymod.class/warrior.name
子文件夹路径中的斜杠
注册 ID 的 path 部分保留斜杠(/)。所以翻译键可能是 module.mymod.class/warrior.name(带斜杠)。这合法但在 lang 文件中不太规整。如果你希望规整,有两种选择:
- 数据包使用扁平文件名(避免子目录)
- 显式写
"name": {"translate": "mymod.class.warrior.name"}用点号分隔的 key
三种 i18n 风格
风格 A:依赖自动回退(推荐)
JSON 中 name 缺省,只填 lang 文件:
// data/mymod/epiphany/module/warrior.json
{
"initial_state": "selectable",
"insights": [ ... ]
}// assets/mymod/lang/zh_cn.json
{
"module.mymod.warrior.name": "战士",
"module.mymod.warrior.description": "战场老兵"
}风格 B:显式写翻译键
数据包与 lang 解耦更清晰,翻译键命名自由:
{
"name": { "translate": "mymod.warrior.name" },
"description": { "translate": "mymod.warrior.desc" }
}// assets/mymod/lang/zh_cn.json
{
"mymod.warrior.name": "战士",
"mymod.warrior.desc": "战场老兵"
}风格 C:字面文本(不国际化)
适合只服务单一语言的小型数据包:
{
"name": "战士",
"description": "战场老兵"
}显示语言与玩家客户端语言无关,始终显示此文本。
lang 文件位置
assets/<namespace>/lang/<语言>.json<namespace>通常与你的数据包 / 模组 namespace 一致<语言>见 MC 标准:en_us/zh_cn/ja_jp/ ...
KubeJS 视角
在 KubeJS 脚本中获取玩家看到的本地化文本需特别注意:
let module = Epiphany.getModule('mymod:warrior');
// ❌ 原 Optional(数据包 JSON 中字面的 Component,可能为空)
let rawName = module.name; // Optional<Component>
// ✅ 含 lang 自动回退的展示文本
let displayName = module.effectiveName('mymod:warrior').getString();