国际化与本地化
国际化(简称 i18n)是一种代码设计方式,使代码无需更改即可适配多种语言。本地化则是将显示文本适配为用户语言的过程。
原创说明图,依据 Forge 1.21.x 官方文档 绘制。
i18n 使用翻译键实现。翻译键是标识一段可显示文本的字符串,不属于某种特定语言。例如 block.minecraft.dirt 是泥土方块名称的翻译键。这样就可以在不关心具体语言的情况下引用显示文本,适配新语言也无需修改代码。
本地化按照游戏的区域设置进行。Minecraft 客户端通过语言设置指定区域设置;独立服务器唯一支持的区域设置是 en_us。可用区域设置列表见 Minecraft Wiki。
语言文件
语言文件的路径为 assets/[namespace]/lang/[locale].json。例如,examplemod 提供的所有美式英语翻译位于 assets/examplemod/lang/en_us.json。文件格式是翻译键到值的 JSON 映射,必须使用 UTF-8 编码。旧版 .lang 文件可用转换工具转换为 JSON。
{
"item.examplemod.example_item": "Example Item Name",
"block.examplemod.example_block": "Example Block Name",
"commands.examplemod.examplecommand.error": "Example Command Errored!"
}
在方块和物品中使用
Block、Item 和其他少数 Minecraft 类内置了用于显示名称的翻译键。这些键通过重写 #getDescriptionId 指定。Item 还有 #getDescriptionId(ItemStack),可以重写以根据 ItemStack NBT 提供不同的翻译键。
默认情况下,#getDescriptionId 返回方块或物品的注册表名称,前面加上 block. 或 item.,并将冒号替换为点。BlockItem 默认重写此方法以使用对应 Block 的翻译键。例如,ID 为 examplemod:example_item 的物品实际上需要语言文件中有以下一行:
{
"item.examplemod.example_item": "Example Item Name"
}
注意:翻译键的唯一用途是国际化。不要用它实现逻辑,应使用注册表名称。
本地化方法
警告:常见问题是让服务端替客户端进行本地化。服务端只能按自身的区域设置本地化,该设置不一定与已连接客户端的区域设置相同。
为了尊重客户端的语言设置,服务端应使用 TranslatableComponent 或其他保留语言中立翻译键的方法,让客户端按自己的区域设置本地化文本。
net.minecraft.client.resources.language.I18n(仅客户端)
此 I18n 类仅存在于 Minecraft 客户端,供只在客户端运行的代码使用。尝试在服务器上使用它会抛出异常并导致崩溃。
get(String, Object...)使用客户端的区域设置进行本地化和格式化。第一个参数是翻译键,其余参数是String.format(String, Object...)的格式化参数。
TranslatableContents
TranslatableContents 是延迟本地化和格式化的 ComponentContents。它在向玩家发送消息时很有用,因为消息会自动按玩家自己的区域设置本地化。
TranslatableContents(String, Object...) 构造函数的第一个参数是翻译键,其余参数用于格式化。只支持 %s、%1$s、%2$s、%3$s 等格式说明符。格式化参数可以是 Component,它们会被插入结果文本并保留所有属性。
可以向 Component#translatable 传入 TranslatableContents 的参数来创建 MutableComponent,也可以向 MutableComponent#create 传入 ComponentContents 本身来创建。
TextComponentHelper
createComponentTranslation(CommandSource, String, Object...)根据接收方创建本地化并格式化的MutableComponent。如果接收方是原版客户端,则立即执行本地化和格式化;否则,通过包含TranslatableContents的Component延迟执行。只有服务器需要允许原版客户端连接时,此方法才有用。
原文:Internationalization and Localization。
译注:原文提及
TranslatableComponent和ItemStackNBT,相关内容可能滞后;请核对目标版本的 API,示例尚未编译验证。