翻译包存放在Language文件夹内,并使用预设好的名字来区分语言。
以下是一些常用的语言的文件夹名:
ChineseSimplified 简体中文
ChineseTraditional 繁体中文
English 英语
Japanese 日语
Russian 俄语
一个翻译包分为两部分:对def内文本的翻译放入DefInjected文件夹,对dll内的翻译放入Keyed文件夹。对dll的翻译被称为Key,基本格式为:
<key>文本</key>
在整个游戏所有已启用的mod中不允许出现重复的key,否则排序靠后的将覆盖排序靠前的。
若游戏使用的语言所对应的翻译包中缺少对应的key,或者干脆没有对应的翻译包,那么会从English包中查找并使用。
由于我们目前不对程序,dll方面展开教学,Key的内容就到此为止,对于def的翻译是本章的主要部分。
与defs不同:
Defs区分一个def的类型是看它在数据库中出现时最外层的参数名,例如现在defs中有这样一个文件:
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThingDef ParentName=”XFMLI_ThingParentA”>
<defName>XFMLI_Flower</defName>
<label>flower</label>
<description>A beautiful flower</description>
</ThingDef>
</Defs>
第一行为识别码,所有xml文件的必需,在作为例子的这个thingdef中,我使用了父对象来省略其他必要的数据填写,这样一来我们就更能将注意力集中在这三项研究对象上。
我们注意到,defs中总是用一个参数名放在最外层来区分类型,显而易见的,此处的例子中的def类型为thingdef
而翻译包并不采用这种形式,在这里我们通过文件夹的命名来区分其中的翻译文件所对应的def类型。对于上文的例子,我们如果要制作翻译,那么应当将文件置于下图的文件夹中:
<?xml version="1.0" encoding="utf-8" ?>
<languages>
<XFMLI_Flower.label>花</XFMLI_Flower.label>
<XFMLI_Flower.description>一朵美丽的花</XFMLI_Flower.description>
</languages>
基本格式为:
<defName.数据路径>翻译文本</defName.数据路径>
其中defname为你要翻译的def的defname。
数据路径指的是从整个数据体最外层向里依次拆分复合数据直到到达翻译对象。一个文本的基本数据每级的参数名之间用小数点连接,再举一例:
<数据体>
<defName>X</defName>
<复合A>
<复合B>
<基本C>this.</基本C>
</复合B>
</复合A>
</数据体>
其对应翻译为:
<x.复合A.复合B.基本C>这个。</x.复合A.复合B.基本C>
特别的在于list型复合数据,因为它拆分后是多个元素。也就是li。我们当然不能在路径中使用li,而应当使用索引器:用一个从0开始依次增加1的整数来依次指代元素。注意其从0开始数意味着第一个元素为0,第二个为1,依此类推。
如:
<list>
<li>A</li>
</list>
即为<list.0>A</list.0>
而除此之外,其实还有其他对list的元素的索引方式,如
翻译文件直接用label来索引,注意索引到的是元素本身,所以依然需要一个label来指向其名字文本数据。
在comps中,也常直接用Class名来指代,当然也可以用comps.0来指代。值得注意的是,对于父对象的翻译不会作用于子对象上,也就是说,即使子对象在继承后拥有与父对象完全相同的一个文本数据,你仍然要对它们分别翻译,而一个abstract=”true”的数据体其中的任何数据都是不允许被翻译的——当然,在正常情况下这种数据体也不存在defname。
除此之外,原文本中若出现形如 {n}(n为整数)或 “TargetX”(X为大写字母)等,则需要保留他们在翻译文本中。
<stringA>Use this by TargetA.</stringA>
<stringB>The number is {0}.</stringB>
对应的翻译为
<stringA>让 TargetA使用这个。</stringA>
<stringB>数字是{0}。</stringB>
你可以自行安排它们在文本中的位置,在该文本实际出现在游戏中时,它们会自动被程序替换为其他东西。
如果一个def没有找到对应的翻译,将直接使用def中的文本,而不是English翻译包。因此我鼓励大家在制作时以英文书写def中的文本,再用中文翻译来完成中文文本。