→ Skip to: php.mo on Github
When making translatable/internationalised websites (a process known as i18n, short for ‘internationalization’), many people and software projects use the
gettext library, which in PHP often looks like this:
<?php _('My Cool Text');?>.
This code, used instead of a standard echo or print, will look for a translated version of the input string (in the .mo file specified at the top of the application/software) and output it, or if it hasn’t been translated, will output the original English text by default – which is nice.
Basically, this means that if Mr. Webmaster hasn’t translated the string “whatsup, dickface” into Italiano, the visitor will just see that text, instead of an ugly untranslated “welcome_msg” text, or a total blank.
So there are many methods to make the translation catalogue files (called .po files) which list every piece of English text and its representation in the foreign language, along with helpful hints to translators. The most widely used program is Poedit.
Poedit has some serious quirks and could definitely use a UI upgrade (1998 called… they want their interface back) – but it works, and when you save a project, it not only generates the .po file (which can be opened and edited in the future), but also, a binary ‘machine object’ (.mo) file, which although unreadable to us, is the much faster of the two for a script to run from.
But if you’re using a custom build script to generate .po files from, say, a Google Documents spreadsheet with all the translations for every language in it (as on my latest project – it’s fairly easy as it happens), you need to also generate .mo files (not so easy, unless you speak binary.)
So I needed a way to generate binary .mo objects from the ready-converted .po files, so that gettext could translate the site.
I found this handy command that seemed to work great:
$ msgfmt -cv -o /path/to/output.mo /path/to/input.po
But, in order for this to run, you need the gettext library installed (which may well be installed by default,) and, I think, probably a few other things. And even though it went great in the terminal, I couldn’t get it to run inside exec() – and I can’t vouch for the configuration of the system on which the convertor script is going to be run in the future.
A little more googling led me to a piece of code from 2007, called php-msgfmt, which is a command-line PHP script. I couldn’t get the thing to work reliably form the command line or from PHP, but I did steal the .mo file-converting functions – which seem to be absolutely rock solid (credit given!)
php.mo is a couple of functions that take an input (.po) file and generate an output (.mo) file. Usage is easy:
<?php require('php-mo.php'); phpmo_convert( 'input.po', 'output.mo' ); ?>
Just like that. You can even leave the second parameter blank, and the output file will take the same filename as the input file, with a .mo extension.
I’ve double-checked the phpmo-generated .mo binary files with those generated by Poedit, and they seem to be identical – which leads me to believe that this is production-ready.
The code is on Github, for all your .po to .mo needs – enjoy!
PS. Make sure to hit ‘Watch’ on the repository if you’re interested in gettext, translations and internationalisation – I’m planning to release a bunch more PHP scripts into the php.mo project for various other useful gettext-ey functions.