Login

如何本地化插件

原文:HOWTO:_Localize_an_AddOn,发表于WoWWiki

译者:流润之风

剪贴自 http://forums.curse-gaming.com/showthread.php?t=259 ,感谢 Islorgris.

这是一篇介绍如何对插件进行基础本地化的“小”帖子(译自WoW法文UI定制论坛)。

总而言之,这篇文章很简单,我希望看完之后,插件作者们能有一些本地化需求的概念,用户们也会对本地化需要哪些信息有所了解。

Locale

Locale 是用于获知接口采用何种语言,从而决定一个本地化插件执行何种代码的东西。

通常,它用于GetLocale代码块:

代码:

   if (GetLocale() == "frFR") then
       -- things for the french client
   else
       -- for the rest, usually english since it's the default language
   end

变量

简而言之,成功的插件本地化,就是用你想要采用的语言为你想要使用的元素(文本、物品名、法术、等等)翻译接口文字。

所以,所有的文字(好吧,几乎所有)都应该被替换为变量,将这些变量设置在 GetLocale 代码块中,从而对于每个 locale,这些文字都能获得正确的值。

目前,最好的做法是将这些变量放入一个单独的文件,与主代码隔离(为了便于引用,通常取名为localization.lua,但可以是任何文件名)。

然后,必须在插件的 xml 中、其他脚本文件之前声明该文件,例如:

代码:

   <Script file="localization.lua"/>
   <Script file="GatherIcons.lua"/>

如果这是准备提交给作者的一个插件修改版,那么最好用英语作为变量名,并加上插件名作为前缀(防止与游戏变量和其他插件的变量冲突),保留原始字符串,将它们作为值赋给变量,这样原作者就能将它们和原始的代码匹配起来(另外,别忘了加上注解)。

例如: 代码:

   if (skillName == "Herbalism") then
       GatherSkills.herbs = skillRank;
   elseif (skillName == "Mining") then
       GatherSkills.mining = skillRank;
   end

变为: 代码:

   if (skillName == GATHERER_TRADE_HERBALISM) then
       GatherSkills.herbs = skillRank;
   elseif (skillName == GATHERER_TRADE_MINING) then
       GatherSkills.mining = skillRank;
   end

变量 GATHERER_TRADE_HERBALISM 和 GATHERER_TRADE_MINING 的定义在 localization.lua 中,如下:

代码:

   if( GetLocale() == "frFR" ) then
       -- french part
       GATHERER_TRADE_HERBALISM="Botanique";
       GATHERER_TRADE_MINING="Minage";
   else
       -- default, english
       GATHERER_TRADE_HERBALISM="Herbalism";
       GATHERER_TRADE_MINING="Mining";
   end

可以看到,仅仅是将双引号间的原始字符串替换成了相应的变量。

警告:在 xml 文件中使用本地化字符串时,必须将变量名用双引号括起来。

示例:

代码:

   [FontString name="bcTM_PopupTitle" inherits="GameFontHighlight" text="TRACKMENU_TOOLTIP_MENU_TITLE"]

该代码允许 xml 元素使用变量 TRACKMENU_TOOLTIP_MENU_TITLE 的内容。

语法和大小写敏感性

这一节只对处理(从聊天窗口获取的)句子(例如保留句子中的某部分)有用。这时有必要添加一个 GetLocale 代码块,因为不同语言的单词顺序有可能会不同。

示例:

引用:

   copper vein => veine de cuivre  

另外,受此影响,由于单词顺序的不同,大写也会出现在不同的单词上。

示例:

引用:

   Damaged chest => Coffre endommagé
   Small damaged chest => Petit coffre endommagé

重音、特殊字符和元音变音

lua 语言直接将重音作为 unicode 处理,这是有点麻烦的,因为它意味着两件事:

首先,本地化文本中不以 unicode 编码的重音是无法识别的,因而也无法与游戏界面上看到的重音匹配起来。

在前一个示例中,如果你试图将"endommagé"与游戏中出现的相同字符串匹配,结果是不会成功。

其次,unicode 字符是用若干个字符来进行编码的(通常是2个),所以要考虑字串处理中的长度问题。

为了处理重音字符,兼容UTF-8的编辑器是必需的,否则,这些字符会被转化成对等的本地字符,也就无法与游戏中的字符匹配了。

请参考 http://www.allegro-c.de/unicode/zcodes.htm (虽然是一个德语页面,但其中的表格可以很方便地进行查找),这里有一个重音字符编码的列表。

自动转换器:http://black-fraternity.de/lua/utf8converter.php (Source: http://black-fraternity.de/lua/utf8converter.phps)

对于我们前面的箱子示例来说,类似下面的字符串才能匹配游戏中的数据:

引用:

   Coffre endommag\195\169  

一些编码:

   à : \195\160    è : \195\168    ì : \195\172    ò : \195\178    ù : \195\185
   á : \195\161    é : \195\169    í : \195\173    ó : \195\179    ú : \195\186
   a : \195\162    ê : \195\170    ? : \195\174    ? : \195\180    ? : \195\187
   ? : \195\163    ? : \195\171    ? : \195\175    ? : \195\181    ü : \195\188
   ? : \195\164                    ? : \195\177    ? : \195\182
   ? : \195\166                                    ? : \195\184
   ? : \195\167                                    ? : \197\147
   
   ? : \195\132
   ? : \195\150
   ü : \195\156
   ? : \195\159

Unicode

WoW 可以直接识别 .lua 文件中的 unicode 字符,只要该文件是 unicode 格式的。文件的确切格式是“utf-8”。

为了编辑 utf-8 格式的文件,必须采用支持 utf-8 的文本编辑器。而通常的文本编码格式是 iso8859-1。还有些更早的编辑器采用的是 ANSI。

个人最喜欢的编辑器是 EditPad Lite版。它默认采用 ANSI,但可以用 Convert/Unicode/ANSI->UTF-8 功能将整个缓冲区的数据转化成 UTF-8 格式。当然,很多商业软件也可以将文件保存为 UTF-8 编码。

单引号

单引号比较特殊,它在 unicode中 也有对应的编码,但在游戏中却并非总是按照 unicode 处理,需要进行试验。

示例:

引用:

   D\195\169couverte d'herbes ==> 可以匹配游戏中的数据
   Veine d'argent ==> 这个以前不能匹配,不过在1.2.2-4196之后已经可以匹配了.  

作为一条准则,特别要检查来自聊天窗口的数据,因为这是特殊编码代替单引号出现最为频繁的地方(也许在1.2.2-4196之后不再是这样)。

注意:单引号的 unicode 编码是3个 utf-8 字节:

   ’ : \226\128\153 (UCS 2019 -- RIGHT SINGLE QUOTATION MARK)

作为例子,可以在战士技能 Cri d’intimidation的 frFR locale 数据中找到该编码(至少在 1.8.4 能找到)。

检查 GlobalStrings.lua

Blizzard 已经替你做了一些事情,请检查 GlobalString.lua文件(以 interface.mpq 中提取的部分为基础,以及patch.mpq 中提取的部分为最近更新)。这一文件包含了许多预定义的变量,变量值采用的是客户端的语言。

关于表格排序

WoW 中大多数表格都是按字母排序的,也就是说条目排列的顺序取决于它们的翻译。

示例:英语客户端(英国和美国)中卡利姆多大陆的区域名:

   Ashenvale, Azshara, Darkshore, …….

而到了法语客户端,顺序变为:

   Ashenvale, Azshara, Un'Goro Crater (翻译为 "Cratère d'Un'Goro"), …….

第三项是不同的。

比如,有一个基于地区顺序、提供小地图缩放比例的静态表格,它在本地化时就必须注意到不同 locale 的客户端具有不同的排序结果,只有这样才能返回正确的值。

不要过度

并非一切都需要翻译,某些东西如果经过翻译会导致无法工作。一个典型的例子是用于重新构建对象的 lua 对象(通常是变量,有时是函数)和 xml 对象(.xml文件中定义的组件名)。

示例:

   getglobal(EN_DUR_FRAME..FrameName.."SlotLeft"):Show();

在上例中,我们获取一个 XML 对象,并进行显示,这里的对象名是用变量 EN_DUR_FRAME、FrameName和字符串"SlotLeft"拼合而成。

由于对象名是硬编码在 .xml 文件中,对这些名字的改变将会导致错误。

最后润色,.toc 文件

.toc 文件允许通过添加以 locale 为后缀的条目来进行本地化:

示例:

引用:

  • Title: Gatherer
  • Title-frFR: Gatherer (en francais, in french)
  • Notes: Gatherer, displays stuff you gather in your minimap
  • Notes-frFR: Gatherer, affiche les objets recoltes dans la minicarte

后缀 -frFR 向法语客户端表示现在有翻译版本可供使用,而且应该优先于默认版本(默认版本大多是英语),如果没有对应该客户端的“本地化”条目,那么显示的则是默认版本。

补遗(patch 1.4.0):在patch 1.4.0 中,Slouken 在 US 论坛上发布了一个有些模糊的说明,表示将小数点改为欧洲值(即逗号)。受此影响,那些包含点号的表格索引不再有效,由于在 patch 1.4.0 以前的欧洲版中并没有引入该行为,所以要避免在表格的索引中使用点号。

示例:在 patch 之前,这个表格是没有问题的。

   ["FR 1.4.0"] = ...

但在 patch 之后,尝试获取索引内容将会导致错误,因为游戏引擎将它翻译为"FR 1,4,0",当然无法匹配上面的索引。

小贴士

关于如何在各种维护和更新中维持本地化,Sarf 有一些小小的贴士。

请参考本地化信息页面来获取一些已知的本地化字符串的列表(地区、频道、等等)

不要使用物品名称

Q: 如果不用名字,那么怎么引用这些物品呢?

A: 通过它们的 id。

感谢 CastOptions.lua 提供以下代码片段:

function MyAddOn_ExtractItemID(link)
        _, _, id = string.find(link, "Hitem:(.+):%d+:%d+:%d+%\124");
        return id;
end

如果想知道如何获得物品链接,请参考 Global API - Item 系列函数。

使用预定义的、全局的技能名

通过使用预定义的、全局的技能名,就可以动态地改变技能,也不用关心技能的确切名字到底是什么!

还要牢记要把等级和名称隔离。以便集成 GetSpellName(spellID, "bookType")。

隔离本地化代码/变量和普通代码

通常来说,每种语言/地区一个文件是比较合适的。命名惯例通常是 localization<SEPERATOR><LOCALE>.lua

示例(德语本地化):

localization.de.lua

或是

localization_de.lua

localization 文件可以是空文件,也可以只放以下内容:

if ( GetLocale() == "deDE" ) then
    -- todo
end


汉化技术资料类, HOWTOs类, 流润之风

如何本地化插件 (last edited 2007-12-29 07:53:52 by localhost)