5.1 KiB
本地化模块
脚本入口: eve.I18n()
面向游戏的多语言支持:载入按语言分组的翻译表(JSON),按点号路径取字符串、
替换 {name} 占位符、按语言复数规则选择复数形式,并支持缺失键回退到默认语言。
基本用法
i18n <- eve.I18n();
i18n.loadFromFile("zh", "locales/zh.json"); // 从 VFS 读 JSON 翻译表
i18n.loadFromFile("en", "locales/en.json");
i18n.setDefaultLanguage("en");
i18n.setLanguage("zh");
local title = i18n.get("menu.start"); // "开始游戏"
local hi = i18n.getWithParams("greeting", {name = "Alice"}); // "你好,Alice!"
local items = i18n.getPlural("items", 5); // "5 件物品"
产品内容应把全部语言作为一个版本化原子包发布:
local admitted = i18n.replaceBundleFromJson(bundleJson);
if (!admitted.ok) throw admitted.status.summary;
包必须使用 schema: "eve.i18n.bundle"、version: 1、defaultLocale 和
locales。replaceBundleFromJson 会严格拒绝未知根字段、非法或空键、非字符串叶子、
缺少 other 的复数表、语言间缺失/多余键、单复数类型漂移和 {placeholder} 不一致。
验证在候选副本上完成,失败不改变已发布语言、当前语言或默认语言。成功后当前语言若仍存在则保留,
否则切换到新默认语言。hasInLanguage(lang, key) 检查精确语言而不使用回退,
validateKeyCoverage(key) 则以结构化结果验证每个已发布语言都精确拥有产品 key,
缺失诊断会指出具体语言与 key 路径。
getKeyCount(lang) 返回该语言拥有的单数与复数键总数。
翻译表格式
JSON 根节点是对象;值可以是字符串、数字/布尔(转字符串),或复数形式表
(键全部为 zero/one/two/few/many/other 的对象,作为该键的复数形式)。
{
"menu": { "start": "Start", "quit": "Quit" },
"greeting": "Hello, {name}!",
"items": { "one": "{n} item", "other": "{n} items" }
}
- 点号路径:
menu.start→menu -> start。 - 占位符:
{name}/{n}由getWithParams/getPluralWithParams的表或复数计数替换。 - 缺失键:先查当前语言,再查默认语言,最后返回键本身(方便开发期看到未翻译项)。
- 转义:JSON 原生支持
\uXXXX(含代理对)与\n、\"等转义。
复数规则
内置 CLDR 风格规则覆盖常用语言:
| 语言 | 形式 |
|---|---|
en/de/es/it/nl/sv/da/no/fi/el… |
one (n==1),其余 other |
fr/pt |
n∈{0,1} → one,其余 other |
ru/uk/be |
one/few/many 三形式(%10 与 %100 规则) |
pl |
one/few/many |
cs/sk |
one/few/other |
zh/ja/ko/th/vi/id/ms/tr/my… |
无复数区分,恒为 other |
语言代码会截取 -/_ 前缀(如 zh-CN → zh)。选定形式缺失时依次回退
other → one;整键缺失再回退默认语言。
目标导向指南
为多语言配置对话
在 eve_init 中载入翻译表并设置语言,之后所有显示文本(含 Dialogue 台词、
UI 文案、选项标签)都通过 i18n.get* 取,便于后期扩展新语言:
dlg.say("alice", i18n.get("line.hello"));
dlg.addChoice("yes", i18n.get("choice.yes"));
热重载翻译表
loadFromFile 会记录文件路径与修改时间;每帧调用 i18n.update(dt) 即可在
文件变更后自动重新载入(可通过 setAutoReload(false) 关闭):
function eve_update(dt) {
i18n.update(dt);
// ...
}
常见问题
loadFromJson解析失败或根节点不是对象时返回false(错误静默,可用hasLanguage确认)。getPlural只认复数形式表;普通字符串键会原样返回(不做复数处理)。setLanguage只接受已载入的语言,否则返回false且保持原语言。
API 快查
clear()、get(key)、getDefaultLanguage()、getLanguage()、getLanguageAt(index)getLanguageCount()、getPlural(key, n)、getPluralWithParams(key, n, params)getWithParams(key, params)、has(key)、hasLanguage(lang)isAutoReload()、兼容入口loadFromFile(lang, path)/loadFromJson(lang, json)、 结构化入口replaceLocaleFromFile(lang, path)/replaceLocaleFromJson(lang, json)replaceBundleFromJson(json)、selectLanguage(lang)、hasInLanguage(lang, key)、validateKeyCoverage(key)、getKeyCount(lang)setAutoReload(enable)、setDefaultLanguage(lang)、setLanguage(lang)、unload(lang)update(dt)
params 是 Squirrel 表,值为字符串 / 数字 / 布尔时自动转字符串;非表或
null 视为空参数。
使用要点
- 模块对象和翻译表应一次性载入并保存在全局状态,不要在每帧重复载入。
update(dt)应在eve_update调用;文本查询可在更新或渲染阶段进行。- 参数约束、默认值和返回类型以头文件与
addFunc绑定为准。
源码: src/modules/i18n/
相关测试: 在 test/ 中搜索 i18n。