本地化你的插件

  • by Rainer Erich Scheichelbauer
  • Tutorial

所以你写好了很棒的插件,它也和预想一样正常工作。但是随后收到的抱怨就像这样:“Que? No español?”或者“Qu’est-ce que ça veut dire? Pas de Français?”甚至是“Jahimmelherrgottkruzifix, gibt’s denn koa Boarisch?”

简而言之,你的插件仅有英文版,但是你的用户可能在其他语言环境下运行软件。如果你不讲他们的语言,通常当你询问他们如何翻译界面时,他们会非常配合。你应该做的是仅仅使用谷歌翻译过一遍文本,这样你的用户可能会非常困惑。我们警告过你了。

第一步:将你的 .nib 和 .xib 文件放入 Base.lproj

要让翻译内容正常工作,我们需要把需要翻译的文件放在一个特别的子文件夹中。原始未翻译的文件被称作“基文件”(Base)。这样,子文件夹需要命名为 Base.lproj,因为这就是我们“语言项目”(language project)的“基文件”。

好,那我们开始。右键单击插件,选择“显示包内容”进入其中。在这里,前往“Contents > Resources”。你会在这里找到你的“plugin.py”、“IBdialog.nib”和“IBdialog.xib”文件。万一你做了更加复杂的界面,就会有更多的 .nib 和 .xib 文件。

  1. 确定基文件。选中所有 .nib 和 .xib 文件:

  2. 将基文件放入子文件夹。右键单击并在弹出的上下文菜单中选择“用所选项目新建文件夹”:

  3. 命名基文件夹。将新建的文件夹重命名为 Base.lproj

    注意:名称区分大小写,所以 B 为大写,其余小写。

“Base.lproj”文件夹是基础,现在我们添加特定语言的“.lproj”文件夹,包含基文件的翻译版本。但是首先,我们需要创建英语的 .lproj。你没读错,是英语。

第二步:添加英语的 .lproj 文件夹

我们为什么需要一个英语的语言项目文件夹?毕竟插件本来就是英语的了。所以有人会觉得你只需要再做翻译就可以了。嗯,不完全是这样。要点在于,基文件不应有所改动或者改动尽量小,因为你要不遗余力地避免 ID 的变动。(在本教程的后文中你就会读到关于 ID 的内容。)这意味着如果之后你想对英文版文本进行更改,比如想要更正一处拼写错误,那么你需要在“.lproj”文件中更改,而不再是原始的“.xib/.nib”文件。

  1. 创建语言文件夹:在你刚刚新建的“Base.lproj”文件夹旁,新建名为 en.lproj 的文件夹:

  2. 为每个 .nib 文件添加 .strings 文件:然后启动你最喜欢的文本编辑器,比如 AtomSublimeText 或者 TextMate,新建文件,以 IBdialog.strings 命名,并保存在“en.lproj”文件夹中:

    文件名必须和“Base.lproj”中的 .nib 文件相同。文件名同样区分大小写,大写的 IB,小写的 dialog,以及 .strings 后缀名。

    如果你在“IBdialog”之外还有其他的 .xib/.nib 文件,请添加相应的 .strings 文件,和每个 .nib 一一对应。

这就是第二步的内容了。如果你都正确操作,看上去差不多像这样:

到目前为止都不错。不过一个空的 .strings 文件也没有什么用。我们要添加一些内容,所以先不要关闭这个文件。

第三步:为英语的 .strings 文件添加内容

我们现在需要做的是告诉插件某个指定的文本内容如何变为新的文本内容。为了实现这一点,我们需要为每个元素指定 ID,并为其中的一个属性,特别是 title ,指定一个新的字符串。

  1. 找到 ID:用 Xcode 打开“Base.lproj”中的 .xib 文件,选择需要翻译的文本框说明部分(cell)。注意:确保所选的是文本 cell 而不仅仅是文本框本身。这非常重要,因为 cell 和文本框拥有不同的 ID。打开左侧边栏中“对话框”(Dialog)的小三角标志,你可以看到所选择的元素被高亮标出,如以下截图所示。

    然后,保持文本 cell 仍被选中,在右侧边栏中选择“身份查看器”(Identity Inspector,第三个按钮)。现在,在边栏中找到“文档”(Document)面板,选择并复制“对象 ID”(Object ID),粘贴在你的 .strings 文件中。一个不错的办法是在由 /**/ 标记的注释中添加一段说明文字或原始英语文本,这样你不需打开 .xib 文件就可以知道该 ID 代表什么。所以现在,你的 .strings 文件看起来应该像这样:

    /* "Offset" */
    STH-Ua-fbl

    对于其他所有的文本 cell 都这样做。如果你有和对象 ID 相关联的占位文本或工具提示,考虑也把它们添加进来。
     

  2. 找到属性:对象 ID 代表对象,但我们想做的是“在不同语言设置的环境下为它们的属性指定新的值”。用能看懂的语言表述,就是我们要将文本 cell(即“对象”)所带的说明文字(即“属性”)翻译出来(即“指定新的值”)。

    为了给属性指定合适的关键词,看一下“身份查看器”(Identity Inspector,右侧边栏中的第三个按钮)或“属性查看器”(Attributes Inspector,第四个按钮),把你所看到的的名称转换为驼峰式大小写(首字母小写),这就是属性的关键词了。比如,“Tool Tip”变成 toolTip,“Title”变成 title,“Placeholer”变成 placeholder

    你会看到那里也有许多其他的属性,用同样的方式处理它们。不过通常对于翻译而言,只有带文本内容的属性才有理由被包含在你的 .strings 文件中。
     

  3. 整理你的 .strings 代码。.strings 文件的内容必须使用 C 语言的表示法,所以我们的代码必须像这样变形:

    /* "Offset" */
    "STH-Ua-fbl.title" = "Offset";
    1. 将属性作为“点后缀名”加在 ID 后面:STH-Ua-fbl.title
    2. 将带有后缀名的 ID 用直引号括起来:"STH-Ua-fbl.title"
    3. 加上一个等号:=
    4. 加上用直引号括起来的指定文本:”Offset"
    5. 在这行的末尾,添加一个分号:;
    6. 在检查一下噫的注释是否在 /**/ 之间。

    对你想要翻译的所有属性都这样做。如果一切操作无误,你的文本编辑器会帮你将句法着色,看起来就像这样:

同样,一个对象可能包含不止一个你想要翻译的属性。我们的例子看上去也可能是这样:

/* "Offset" */
"STH-Ua-fbl.title" = "Offset";
"STH-Ua-fbl.toolTip" = "Width of the shape contour";

以上即为步骤三。牢记在心,将来你需要在这个 .strings 文件中作改动,而不再是 .xib 文件了。

第四步:创建非英语的 .lproj 文件夹

我们已经设置好了基文件和英语的语言项目(.lproj),我们还需要为想要支持的每种语言建立一个语言项目文件夹。它们和我们已经创建的“en.lproj”完全相同,只是在我们的 .strings 文件中,我们需要添加各自语言的翻译。

专业提示:由于你频繁打开 .strings 文件,考虑每次都用你选择的文本编辑器打开它们。在访达(Finder)中打开文件简介(Cmd-I 或 Cmd-Opt-I),在“打开方式”下选择你偏好的应用程序,然后点击“全部更改…”按钮。

好,我们开始吧:

  1. 创建特定语言的语言项目文件夹。在访达中选择“en.lproj” 文件并制作副本(文件 > 复制,Cmd-D),然后将新文件夹重命名为ISO 639-1 的两位语言代码后接 .lproj 后缀:

  2. 添加翻译。在每个 .lproj 文件夹中,打开 .strings 文件,更改等号右侧直引号之间的文本。

一些建议:如果你不懂相应的语言,考虑把 .lproj 文件夹发送给你的插件的用户,请求他们帮助你翻译这些文字。如果你谁也不认识,考虑在论坛发个帖子来请求帮助。对于插件而言,通常要翻译的文字很少,很容易就能找到愿意免费帮忙的人,尤其是当你的插件本身也是免费的情况下。如果是商业插件,考虑提供一份免费的插件作为回报。

当然,你可以添加任何语言。不过首先,考虑 Glyphs 已经有本地化版本的那些语言。这样,你就可以为这些语言的用户提供更加顺畅的界面体验:

  • cs:捷克语
  • de:德语
  • en:英语
  • es:西班牙语
  • fr:法语
  • it:意大利语
  • ja:日语
  • ko:韩语
  • pt:葡萄牙语
  • ru:俄语
  • tr:土耳其语
  • zh_CN:汉语(简体中文,中国大陆)
  • zh-Hant:汉语(繁体中文,台湾)

你可以看到列表中“汉语”出现了两次,带有不同的后缀名。这是因为它需要在两种可能的书写变体中加以区分:简体和繁体。前者在中国大陆使用,后者用于台湾地区。
 

第五步:重新编译一次 .xib 文件

还有一件事情要做。因为我们将插件转换成了区分基文件和特定语言的版本的本地化项目,我们需要再次将 .xib 编译为 .nib。

你可能知道该怎么做:用“终端”app 打开“Base.lproj”文件夹,键入 ibtool IBdialog.xib --compile IBdialog.nib 并按下回车键。或者,更好的办法,将 .xib 文件推拽到“Compile .xib to .nib.app”上。该程序在 GlyphsSDK 库上提供,能够为你带来方便。

专业提示:你可以将“Compile .xib to .nib.app”设为 .xib 文件的默认打开方式。然后你只需要双击 .xib 文件,然后就完成了。

好消息:你只需要这样做一次。后续所有翻译的增加和更改只需要在 .strings 文件中做,然后就好了。击掌!

第六步 :本地化你的 Python 代码中的文字

我们忘了说什么吗?是的。如果你的插件是用 Python 写的,也许你的 .py 文件中也有一些字串需要翻译:通常是菜单中的名称,也可能是按钮上的单词,如果你的插件有上下文菜单则也可能是其中的菜单项。

在这种情况下,我们可以在 .py 文件中完成。只要把所有字串(包括 Unicide 文本串)替换为 Glyphs.localize() 函数即可。localize() 函数接受 dict 作为参数,dict 即为两位语言代码,相应的值为翻译内容,最好为 Unicode 文本串。

作为例子,你需要将这个:

self.menuName = 'Shadow'

……变成这样:

self.menuName = Glyphs.localize({
    'en': u'Shadow',
    'de': u'Schatten',
    'fr': u'Ombreur',
    'nl': u'Schaduw',
    'es': u'Sombrear',
})

注意文本串之前的 u,它会将文本串返回为一个 Unicode 字符串。如果你的翻译中包含非 ASCII 字符,你便需要这个 u。不过,保持安全并没有什么坏处,所以总是加上吧。如果在 .py 文件中使用 Unicode 字符串,最好在文件的开头声明编码,像这样:

# encoding: utf-8

顺便说,这也适用于插件之外的所有常规 Python 脚本。它甚至可以很好地与普通代码集成。很酷。

好,我想就是这些了。现在你已经掌握了所有用于本地化插件的工具。一旦你掌握了窍门,你会发现这是一种很极客的乐趣,根本停不下来。所以,尽情地把自己的内心本地化出来吧。:-)

测试本地化

要测试本地化,首先确保你没有勾选“Glyphs > 偏好设置 > 用户设置 > 停用本地化”。否则,你将不能将 Glyphs 切换为另一种语言。

然后前往“系统偏好设置 > 语言和地区”,将你想要测试的语言拖动到列表的最上方。如果看不到该语言,使用“+”按钮添加。比如,要测试西班牙语本地化,在列表中添加西班牙语,然后拖动到最上,像这样:

要确认更改,只需关闭系统偏好设置。一个对话框将询问是否要重启 Mac,不用重启。

不过确实重启一下 Glyphs。

专业提示:重启应用程序最快的方法是右键单击程序坞(Dock)中的图标,按住 Option 键再按方向键下箭头,这样应该就选中了程序坞菜单中的“强制退出”,然后(还不要松开 Option 键!)按回车确认。你刚刚强退了 Glyphs,现在可以重新启动了。因为你的鼠标指针还在应用程序图标之上,只需单击鼠标就能让它跳回运行状态。稍加练习,这个过程便只需一两秒钟。

启动后,Glyphs 便以西班牙语运行了!在 FiltrosVista 菜单中寻找你的插件,它的名称应该已经变成了你为 self.menuName 所设定的日斯巴尼亚名字,然后像这样:

故障排除

好吧,我不能跟你说谎,经常会有一些东西出错。如果翻译内容没有出现,或者你在过程中迷失了方向,以下几个提示可以帮你快速发现问题:

  • 对象不正确:你是否确定通过所找到的 ID 连接到了正确的对象?通常,你可能会不小心用到了指向文本框而非文本框 cell 的 ID。确保在 Xcode 侧边栏的Dialog面板中进入了足够深的层级。看这里,那个带着可爱笑脸的才是你要找的那项:
  • ID 发生变动:你是否修改了 .xib 文件?或许把其中一个文本框替换成了几个别的对象,或是从另一个 .xib 文件中粘贴进来了一个?这样 ID 就可能发生变动。你需要重新编译 .xib 文件,并且再次重点核实一下对象的 ID。
  • 忘了输入分号:在 .strings 文件中,每条指定文本后都必须有一个分号。我没法借你一个不用的分号,很抱歉。
  • 重新编译过一次了吗?你是否在添加过“Base.lproj”后重新编译过 .xib 文件了?再次重新编译也不会花什么工夫,所以安全起见,不论如何再做一次吧。


Chinese translation by Willie Liu (刘育黎) from 3type (三言).