维护并行本地化分支(如CiviCRM所做,同时维护CiviCRM 2.1和CiviCRM 2.2线的最新本地化)的一个问题是,将添加到其中一个分支的翻译应用到另一个分支上的问题。我终于成功编写了一个自动化这个过程的系统——继续阅读了解详情。

由于CiviCRM使用gettext文件来维护翻译,翻译迁移的最简单解决方案就是总是累积新的字符串,并将CiviCRM 2.1中添加的新翻译简单合并到CiviCRM 2.2中。不幸的是,这种方法会使翻译文件变得过于庞大;当面临超过6000个字符串需要翻译时,开始新的翻译已经很难(这就是为什么我们将字符串分为在大多数基本CiviCRM中出现的字符串——保存在civicrm-core.po文件中——和出现在可选模块中的字符串——保存在civicrm-modules.po中)。

在排除了累积法(并回顾了过去十三个CiviCRM版本中的本地化文件)之后,很明显需要创建一个更复杂的解决方案;这个方案能够继承在CiviCRM 2.1中删除、在CiviCRM 2.2中重新引入的字符串的翻译。我最终采用的解决方案是基于包含特定语言环境中所有字符串翻译的通用文件,以及一个包含所有CiviCRM版本字符串的单一“整体”文件。在新翻译出现在分支中之后,一般的流程是刷新该分支的通用文件,然后更新整体文件(从通用文件中提取翻译,如果有选择,优先选择在较新版本的CiviCRM中引入的翻译),然后刷新给定版本(通常是维护中的另一个版本)的所有PO文件,以便翻译任何它仍然包含的字符串。最后一个(可选)步骤是重新编译MO文件,这些是本地化引擎实际使用的gettext二进制文件。

正如最终解决方案所显示的,我最终得到了一个接收参数然后执行所需操作的单一Bash脚本。然而,达到这个结果的过程并不顺利——我最初明显选择的是使用某种构建系统。我花了很多时间评估选择,make是古老而经典的解决方案,Rake是最希望的选择(我的博士学位是用Ruby编写的...),但由于我不想在CiviCRM代码库中引入另一种语言而被放弃,Phing(make/Ant的PHP端口)看起来很有前景,但它缺乏构建系统中在这个案例中非常有用的单一特性,即跳过自上次运行以来未更改文件源的任务。

我认为我们最终可能会将CiviCRM的各种构建脚本迁移到Phing,但我还没有100%确定古老make的优点是否超过了其缺点,因此我最终采用了那个Bash脚本——简单、工作正常且容易迁移到我们最终选择的构建系统。

随着CiviCRM 2.3代码冻结(和我的蜜月假期...)的临近,在与我的导师讨论后,我最终调整了我的项目时间表,将可以进入CiviCRM 2.3的部分安排得更早而不是更晚。