跳到主要内容

本地化

本地化使应用按玩家语言显示文本。翻译保存在本地化文件中,即包含一个或多个语言区域消息的 JSON 资源,各消息由键标识。文本元素或脚本请求某个键后,应用的 I18n 对象 app.i18n 返回当前语言的消息。

文本本地化

本地化文件​

文件格式如下:

{
"header": {
"version": 1
},
"data": [
{
"info": {
"locale": "en-US"
},
"messages": {
"title": "Treasure Hunt",
"coins": ["You have {number} coin", "You have {number} coins"]
}
}
]
}
  • header.version 必须为 1,否则文件会被拒绝,控制台记录错误。
  • data 为各语言区域保存条目,一个文件可包含一种或多种语言。
  • 消息可为字符串;根据数字变化的文本则使用字符串数组,分别对应语言的各复数形式。

编辑器设置的 LOCALIZATION 区域中,CREATE NEW ASSET 会创建此格式的文件。

复数形式​

各语言的复数形式数量不同,数组按其采用的 Unicode 复数类别排列:zero、one、two、few、many、other。引擎内置以下语言规则:

形式语言
一种:other中文、印度尼西亚语、日语、韩语、泰语、越南语
两种:one、other丹麦语、英语、芬兰语、德语、希腊语、意大利语、挪威语、西班牙语、瑞典语、土耳其语和乌尔都语中,one 对应 1;法语、印地语、波斯语和葡萄牙语中,one 对应 0 或 1
四种:one、few、many、other波兰语、俄语、乌克兰语
六种:zero、one、two、few、many、other阿拉伯语

其他语言使用英语规则。

加载文件​

app.i18n 会在本地化文件加载后读取它,但不负责发起加载:

const english = new pc.Asset('en-US', 'json', { url: 'localization/en-US.json' });
const french = new pc.Asset('fr-FR', 'json', { url: 'localization/fr-FR.json' });
app.assets.add(english);
app.assets.add(french);

app.i18n.assets = [english, french];
app.assets.load(english);
app.assets.load(french);

创建应用时注册 pc.JsonHandler。若已有数据,可直接传给 app.i18n.addData()。

选择语言区域​

当前语言为 app.i18n.locale,默认 en-US,不会自动读取浏览器设置。包括编辑器发布的应用,也会以 en-US 启动,直到显式选择。可以根据玩家选择或浏览器语言设置:

app.i18n.locale = navigator.language;

每个语言区域不一定都有独立数据。例如,没有 fr-CA 时,会使用 fr-FR 或其他法语区域;完全没有法语数据时,回退到 en-US。app.i18n.findAvailableLocale('fr-CA') 返回实际将使用的区域。

切换语言会更新全部本地化文本元素。HTML 等其他内容可监听 change:

app.i18n.on('change', (locale, previous) => {
document.documentElement.lang = locale;
});

编辑器设置 EDITOR 下的 Locale 仅用于视口及启动应用的预览,不影响发布构建。

本地化文本元素​

具有 key 的文本元素显示当前语言对应消息,并随语言切换。找不到消息时显示键本身。

const heading = new pc.Entity('heading');
heading.addComponent('element', {
type: pc.ELEMENTTYPE_TEXT,
fontAsset: font.id,
key: 'title',
anchor: [0.5, 1, 0.5, 1],
pivot: [0.5, 1]
});
screen.addChild(heading);

设置 text 会清除键,设置 key 会替换文本。

复数消息键会显示第一种形式,并保留 {number},因此应通过脚本设置此类文本。

脚本中的字符串​

getText 返回当前语言消息,缺失时返回键本身。getPluralText 按数字选择复数形式,但保留 {number},需要自行替换:

const title = app.i18n.getText('title');

const count = 3;
const coins = app.i18n.getPluralText('coins', count).replace('{number}', count);
// "You have 3 coins"

两者均可通过最后一个可选参数指定语言区域。

本地化字体​

字体资源可以为不同语言区域指定替代字体,适合需要原字体未包含字符的语言。切换语言后,本地化文本元素改用对应字体,并在需要时加载。没有键的元素仍保留原字体。

  • **编辑器:**选中字体,在检查器 LOCALIZATION 区域单击 Add Locale,再选择该语言使用的字体。
  • **引擎、React 和 Web Components:**调用字体资源的 addLocalizedAssetId:
latinFont.addLocalizedAssetId('ja-JP', japaneseFont.id);

新语言字体加载期间,文本不会绘制。

数字与日期格式​

不同语言区域采用不同数字、价格和日期格式,可用浏览器 Intl 对象及当前语言格式化:

const price = new Intl.NumberFormat(app.i18n.locale, { style: 'currency', currency: 'EUR' }).format(4.5);
const today = new Intl.DateTimeFormat(app.i18n.locale, { dateStyle: 'long' }).format(new Date());

语言说明​

中文、日文和韩文​

文本元素支持在中日韩字符之间无空格换行,并将闭合标点和小假名尽量保留在前一行。字符集较大,应参考选择字符,并使用本地化字体。

泰语​

泰语词间没有空格,而文本元素仅在空格、制表符、连字符和零宽空格处换行。可让译者在词间加入零宽空格 U+200B,以支持换行。

从右到左的语言​

文本元素从左到右布局。阿拉伯语、希伯来语等需要先重排字符,阿拉伯语还需处理连写。从右到左语言支持教程提供相应脚本。

另请参阅​

  • 文本元素:绘制、换行与适配。
  • 字体:创建资源和选择字符。
  • I18n:app.i18n API 参考。