Using jython to internationalize a PHP app

At first, this might seem a mind-boggling combination. What do

jython and PHP have in common (excepting the fact that I am a Python fan

and my current consulting task is in a PHP project) ?

Well, internationalizing a PHP app is pretty much a trivial task.

If you are a sensible PHP programmer insisting to use PEAR instead of randomly choosing a script from the tons of snippets

populating the “scripting websites”, I18N is probably the

safest choice.

Maybe – for you – application maintainability and performance are not exactly important concerns.

For me, they are. This is why I chose to store internationalized texts in files rather than database.

I'd rather keep the database for real data, which is created, modified, aggregated and such.

And I'd rather like to have an internationalized error message on the screen even if the database is down.

Now we know that we'll use I18N and text will be kept in some php files. However, I am no professional translator and

have no desire to translate or to manually maintain the correspondence between translators files and PHP files

(no, translators won't modify PHP code, stop this nonsense right away).

Code generation comes immediately in mind.

Basically, my first idea was to investigate wether the files used by the translators can be quickly transformed to PHP,

and if I am able to generate their formats from my own files (aka. “roundtrip internationalization process” ?).

Unfortunately, this is not an easy task – as the only clue was that the translators use Office tools such as Word or Excel, because they

rely upon some specialized translation software integrated with these products.

The easy choice is Excel, since it allows a better organization of data than having to search for tables in a Word document.

The hard choice is the tool that I'd use for automatically reading and even generating Excel files.

The difficulty comes from the fact I don't have Windows with Office installed on my desktop, just Gentoo Linux and OpenOffice.

Thus, I am unable to write a simple Python script which could perform my generation tasks via automation.

Fortunately, this is not the first time I am confronted with the issue.

I happen to know that there is a very nice Java tool that I wholeheartedly

recommend for your Excel processing needs :


Still, Java is a heavyweight programming language – it would be a really bad idea to fire up the

monster just for some easy processing of Excel files.

Here's why Jython comes naturally into equation. Four hours and about

100 lines of debugged code later, here I am sitting on top of a perfectly functional internationalization tool which :

  • generates PHP code from a big xls file (the root vocabulary) which centralizes all the internationalization texts

  • generates 2-language xls files for translators usage

  • updates the root vocabulary starting from the files modified by the translators

  • Automation scripts are already in cron and there's also a nice text document explaining translators where to get

    their files and where to put them after modification. The resulting script is not exactly fast, but this is tooling

    and not production so this should not be a problem after all.

    Whatever your project contraints are, give Jython a try and you'll be amazed … As they put it on the

    Useless Python site – If it were any simpler, it would be illegal.

    Finally there's a trick not quite related with Jyhon, nevertheless interesting.

    There is an easy way of solving the problem of translating phrases with real data inside them, with easy parameter swapping.

    We'll use the good old sprintf but not directly. We'll pass through a not so popular but extremely useful function,

    call_user_func_array. Suppose that our example needs the

    user name and authorization profile description to display inside a nice message. All you have to do is to define placeholders

    in I18N files which would fit as the first argument for sprintf. The following example should make it clearer:


    $messages = array('loggedin'=>'You are authenticated successfully as user %1$s with profile %2$s.');$this->set($messages);


    $messages = array('loggedin'=>'Vous avez le profile %2$s en tant qu'utilisateur %1$s.');$this->set($messages);

    Simple passing of multiple parameters to I18N in PHP. Example function without error processing or data domain checking.

    #this is the multiple parameter functionfunction complexTranslation($i18n, $label, $params){ return call_user_func_array('sprintf',array_merge(array($i18n->_($label)),$params));}

    Then, you have to initialize your I18N object. This can be done in a generic manner for all pages.

    #specific I18N initialization stuffrequire_once 'I18N/Messages/File.php';$g_language_dir = dirname($_SERVER['PATH_TRANSLATED']).'/localization/';$i18n =& new I18N_Messages_File($g_langCode,$script_name,$g_language_dir);

    Finally, use the function.

    #translate the successfull login message$loginbox = Tools::complexTranslation($i18n,'loggedin',array($operator->name,$profile->description));