前言
传统情况下,TMod创建文本的方式一般为硬编码或使用.lang文件,而前者不利于翻译的进行,后者的普及率较低。在最近的更新中,tModLoader提供了以hjson支持国际化的方式,让Mod的翻译与多语言支持变得更加便捷。然而,这方面的指南较为稀缺,因此我编写了这篇教程,希望能够有所帮助。
hjson文件
基础
tModLoader使用hjson文件存储翻译文本。hjson的格式与json基本相同,但是有一些区别:
- hjson不需要在项间添加逗号。
- hjson不需要在字符串两端添加引号。
- hjson可以使用注释。
- hjson支持以 ”’ 包裹的多行字符串。
- hjson不需要在最外层添加大括号。
例如,对于
{ "Root": { "First": { "A": "一", "B": "Two Second" }, "The Second": { "C":"Three\nThird" } } }
的json,在hjson中可以写为
Root:{ First: { A: 一 //单行注释 B: Two Second # 还是单行注释 } /* 多行 注释 */ "The Second": { C: ''' Three Third ''' } }
更全面的介绍请参照这里
另外,上述结构的树状结构为
额外语法
此外,tModLoader中的hjson还支持颜色与引用。
如果需要编写彩色文本,可以使用 [c/16位颜色代码:字符串] 的格式。例如,
普通文本[c/FF0000:红色文本]普通文本
这样的文本会显示为
普通文本红色文本普通文本
引用的语法为 {$路径} 。例如,在上述例子中,{$Root.First.B} 相当于 Two Second 。
引用的效果可以随着自动改变。例如,如果一个名叫Mods.MyMod.Common.Key的项在en-US.hjson中为 English ,在zn-Hans.hjson中为 中文 ,那么,当语言选择为中文时 {$Mods.MyMod.Common.Key} 将会显示为 中文 ,而在选择英文时将会显示为English。
因此,为了减少自己与翻译者的重复操作,建议尽可能多地使用引用。
在Mod中使用语言文本
注意: 此章节适用于1.4.0.1~1.4.3.6的tModLoader, tML在1.4.4采用了不同的方法, 参见Wiki的本地化指南
目录结构
在制作Mod时,语言文本需要放置在 Mod根目录\Localization 中,文件名为 语言代码.hjson 。
例如,名叫 MyMod 的Mod中,中文语言文件的路径为 MyMod\Localization\zh_Hans.hjson
文件结构
在hjson文件中,最外的两层结构是Mods与MODID (MODID换为自己的) 。
Mods: { MODID: { } }
自动使用
tModLoader会自动注册一些常用的文本,这意味着在使用时不需要添加额外代码。
默认情况下,tModLoader会自动注册ItemName, ItemTooltip, BuffName, BuffDescription, ProjectileName, NPCName, MapObject, Prefix等,它们均在hjson文件的第三层。
其中的子项应均为字符串,键为对应的类名,值为需显示的文本。
例如,注册Mod名叫 MyMod ,类名叫 MyItem , 显示为 我的物品 的物品的方式如下:
Mods: { MyMod: { ItemName: { MyItem: 我的物品 } } }
此时,需保证 MyItem 类中 SetStaticDefaults 方法里没有 DisplayName.SetDefault
,否则将无法使用默认引用。
此外,tModLoader还会自动注册其它的一些文本。若需要知道更全面的内容,可以查阅这里
使用Terraria的原生方法
如果要在tModLoader没有自动注册的地方使用语言文本,则需要手动使用。在简单的情境中,Terraria提供了原生的调用方法。
对于字符串常量,只需将原始的字符串替换为 Language.GetTextValue(路径)
即可。(这个方法在Terraria.Localization内)
路径的第一层为 Mods ,用 . 分割。
例如,对于上述例子,若不希望使用tModLoader的自动注册功能,可以将
DisplayName.SetDefault("我的物品");
修改为
DisplayName.SetDefault(Language.GetTextValue("Mods.MyItem.ItemName.MyItem"));
这个方式可以对任意字符串生效。
tModLoader提供的方法
tModLoader额外提供了 LocalizationLoader 类与 ModTranslation 类以更灵活地创建语言文本。这两个类均在Terraria.ModLoader中。
这两个类的目的并非更改调用语言文本的方式,而是提供动态创建语言文本的方式。因此,在调用语言文本时,仍需要使用Terraria的内置方法。
LocalizationLoader
这个类提供了GetOrCreateTranslation与AddTranslation方法,用于创建与使用ModTranslation对象。
其中,第一个有两个重载:
GetOrCreateTranslation (Mod mod, string key)
与
GetOrCreateTranslation (string key)
前者相当于将key替换为Mods.{mod.Name}.{key}.
例如,对上述例子,使用前者时为
GetOrCreateTranslation(MyMod,"ItemName.MyItem")
后者则为
GetOrCreateTranslation("Mods.MyMod.ItemName.MyItem")
这个方法返回一个ModTranslation对象。
第二个只有 AddTranslation(ModTranslation translation)
一个形式,作用是注册该对象,以便后续使用。
ModTranslation
这个类用于加载与修改语言文本,较为常用的方法为
AddTranslation(GameCulture culture,String value)
与
GetTranslation(GameCulture culture)
。
其中,GameCulture为一个集合类,在Terraria.Localization中。可使用对应语言的编号(int类型)或名称(String类型)替换。
前者没有返回值,后者会返回一个String对象。这两个方法的用法均十分明显,在这里不再赘述。
此外,它还有
与 SetDefault(string value)
GetDefault()
方法,相当于上述两个方法中culture设置为英文。
常用使用方法
在使用时,一般将两个类搭配使用。
- 首先,使用
GetOrCreateTranslation
创建ModTranslation对象。 - 然后,调用(与
Language.GetTextValue
搭配)或修改(使用AddTranslation
方法)该对象。 - 最后,如果进行修改,需要使用
LocalizationLoader.AddTranslation
方法注册。
例如,仍对于上述例子,在修改时为:
ModTranslation t = LocalizationLoader.GetOrCreateTranslation(MyMod, "ItemName.MyItem"); t.AddTranslation((int)GameCulture.CultureName.Chinese, "新的名称"); LocalizationLoader.AddTranslation(t);
在调用时为
ModTranslation t = LocalizationLoader.GetOrCreateTranslation(MyMod, "ItemName.MyItem"); String str=Language.GetTextValue(t.GetTranslation((int)GameCulture.CultureName.Chinese)); //使用str
可能会遇到的问题
有时,在更新语言文件并再次生成后,游戏内的文本并没有更新。这时候,只需重新生成一次即可解决。
值得注意的时,中文的语言文件并非zh-CN.hjson,而是zh-Hans.hjson
后记
与Minecraft Mod中方便的多语言支持相比,Terraria Mod的国际化长久以来都是一个问题。目前,汉化者Mod仍未更新到1.4(很有可能不会更新),很多Mod都仅有一个语言,或者硬编码了多个语言;在支持hjson后,逐渐出现了许多汉化Mod,才缓解了这一问题。虽然在自己的Mod中支持国际化无法直接促进Mod的汉化,但无论时从让自己的Mod更加完善,还是提高hjson的使用率上看,这对tMod的发展都是有益的。