One of the issues with maintaining parallel localisation branches (like CiviCRM does, maintaining up-to-date localisations for both the CiviCRM 2.1 and CiviCRM 2.2 lines) is the problem of making translations added to one of the branches to appear on the other. I finally managed to code a system that automates this – read on for details. 

As CiviCRM uses gettext files for maintaining the translations, the first, trivial solution for translation migrations would be to always accumulate new strings and simply merge new translations added in CiviCRM 2.1 into CiviCRM 2.2. Unfortunately, this approach would make the translation files unbeareably large; it’s already hard to start a new translation when one’s faced with over six thousands strings to translate (that’s why we split the strings into the ones that appear in most of base CiviCRM – held in the civicrm-core.po file – and the ones that appear in optional modules – held in civicrm-modules.po).

Having crossed out the accumulation approach (and with a look into the past thirteen CiviCRM releases which sported localisation files) it was clear that a more sophisticated solution must be created; one that would carry over translations of strings removed in CiviCRM 2.1 and reintroduced in CiviCRM 2.2, for example. The solution I ended up with is based on common files containing all of the string translations for a given locale, and a single, ‘monolithic’ file sporting all strings from all CiviCRM versions for the given locale. The general workflow after new translations show up in a branch is to refresh that branch’s common files, then update the monolithic files (which pull the translations from the common files, with preferring translations introduced in a newer CiviCRM version if there is choice) and then refresh all the PO files for a given release (usually the other maintained one) with translations to any strings it still sports. The last (optional) step is to recompile the MO files, which are gettext binaries actually used by the localisation engine.

As can be seen in the final solution, I ended up with a single Bash script which takes parameters and then carries on the desired action. The road to this outcome was not straight, though – my first obvious choice would be to use some kind of a build system for this. I spent quite some time on evaluating the choices, with make being the old, classic solution, Rake being the most desired choice (I write my PhD in Ruby…) which got turned down because I didn’t want to introduce yet another language into the CiviCRM codebase, and Phing (a make/Ant port to PHP), which looks promising, but doesn’t have the one single feature of build systems which would be useful in this case, which is skipping tasks that don’t have to be run if the files they source didn’t change since last run.

I think we might end up porting the various CiviCRM’s  build scripts to Phing, but I’m not yet 100% sure whether the advantages of good old make aren’t outweighting its disadvantages, hence I ended up with that Bash script – simple, working right and being easily ported to the build system we’ll choose in the end.

As CiviCRM 2.3 code freeze (and my honeymoon break…) approaches, after discussing this with my mentor I also ended up rearranging the timeline of my project and making parts that can still make it into CiviCRM 2.3 scheduled for earlier rather than later.