本地化
为每个 locale 注册一份翻译目录(catalog),切换当前 locale,并用 t() 查字符串——都通过
Localization 资源完成。它刻意不依赖 Intl,所以在 Web 与微信上行为一致。
Localization 是**可选(opt-in)**的——在任何系统读 Res(Localization) 之前先装一次它的插件:
import { App, localizationPlugin, LocalizationPlugin } from 'esengine';
app.addPlugin(localizationPlugin);// …或提前预载目录 + 设置初始/回退 locale:app.addPlugin(new LocalizationPlugin({ locale: 'en', fallback: 'en', catalogs: { en: { play: 'Play' }, 'zh-CN': { play: '开始' } },}));import { defineSystem, Res, Localization } from 'esengine';
const setupI18n = defineSystem([Res(Localization)], (i18n) => { i18n.addCatalog('en', { play: 'Play', score: 'Score: {n}' }); i18n.addCatalog('zh-CN', { play: '开始', score: '得分:{n}' });
i18n.setLocale('zh-CN'); const label = i18n.t('score', { n: 42 }); // "得分:42"});addCatalog(locale, entries)把 key 合并进某个 locale——可多次调用追加(后面的会覆盖)。t(key, params?)会插值{placeholder}的值。缺失的 key 回退到 fallback locale,再回退 到 key 本身(一个可见、可 grep 的兜底)。
目录条目可以携带复数形式——CLDR 全集 zero / one / two / few / many / other;
t 会根据 count 参数选出一个(且 count === 0 时若有 zero 形式总是它胜出)。默认选择器
是英语式(one/other);斯拉夫语 / 阿拉伯语等规则用
setPluralSelector(locale, (count) => category) 注册,返回上述六个类别之一。
i18n.addCatalog('en', { apples: { one: '{count} apple', other: '{count} apples' } });i18n.t('apples', { count: 3 }); // "3 apples"Localization 参考
Section titled “Localization 参考”| 方法 | 说明 |
|---|---|
addCatalog(locale, entries) |
把翻译 key 合并进某个 locale。 |
t(key, params?) |
查找 + 插值一个字符串。 |
setLocale(locale) |
设置当前 locale。 |
setFallbackLocale(locale) |
设置 key 缺失时使用的 locale。 |
setPluralSelector(locale, selector) |
为某 locale 设自定义复数规则。 |
availableLocales() |
列出已注册的 locale。 |
has(key) |
key 是否存在于当前/回退 locale。 |
字符串表(.eslocale)
Section titled “字符串表(.eslocale)”
检视器里的 .eslocale 表:每个 key 在当前语言下的值,下方以另一种语言作为翻译提示。
翻译可以作为数据发布,而不是写死在代码里:一个 .eslocale 资产装着一种语言的目录,
游戏只加载它需要的语言。
// assets/i18n/zh-CN.eslocale{ "version": 1, "locale": "zh-CN", "entries": { "ui.title": "UI 控件", "apples": { "other": "{count} 个苹果" } }}在编辑器里创建(内容浏览器 → 右键 → 新建本地化表)或手写皆可。选中一张表,细节面板
就是它的编辑器:键/译文行(支持复数形式)、其他表的参照译文淡显在每行下方、缺失的 key
一键补齐——每次编辑立即保存。显式加载用
Assets.loadLocaleTable(path)(需要本地化插件——否则大声报错),预载用
new LocalizationPlugin({ tables: ['assets/i18n/zh-CN.eslocale'] }),或者让
下面的 Text 绑定全自动加载。导出 cook 永远会把 .eslocale
打进包里——它们按 key 加载,可达性分析看不见它们,所以强制收入。
把 UI Text 绑到 key
Section titled “把 UI Text 绑到 key”设置 Text.i18nKey(编辑器细节面板里的 I18n Key 下拉,列出项目全部表里的 key 及其
译文预览),content 就变成派生值:每帧重新解析,所以 setLocale——或者一张晚到的
表——都会让所有绑定的标签自动重排,零代码。场景驱动的项目免费得到整条链路:只要场景里
有任何绑定的 key,加载时会自动安装插件、加载全部已发布的表,并在有匹配的表时以
玩家的系统语言启动(自己安装插件、或调用过 setLocale 的游戏永远不会被覆盖)。
动态标签(Score: 42)请保持代码驱动——绑定的 content 是派生的,代码会改写的标签
不能同时携带 key;在拥有它的系统里调 t('score', { n }) 即可。
- 一切都经
t()或i18nKey——绝不硬编码面向用户的字符串,连占位符也不。 - 插值,别拼接(
'Score: {n}'),这样语序能因语言而异。 - 设一个回退 locale,让缺失的翻译退化到另一种语言,而不是裸 key。
- 一种语言一个
.eslocale,放在同一目录(assets/i18n/),key 完全一致——缺失的 key 会以 key 字符串可见地兜底。