→ 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.
.po
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.)
.mo
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!)
Enter php.mo
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.


I tried poedit in the past, but it was not working well (at least to me); instead this method is very simple and quick to use (the one with php-mo.php).
Thank you very much, it worked very well!
Glad you liked it, thanks!
Thank you.
Now I can easily regenerate translations on the server side.
Hello Joss!
Great lib!! I’m using it right now, but I’m not getting a valid .mo file.
First thing I see, the size is different (smaller, 4Kb) then the poEdit .mo file (12kb)
Second thing, I’m not able to instantiate this .mo file, translations are not showing, but I’m not getting any error.
I’m thinking that there’s maybe a problem with charset? I’m using UTF-8 on the .po file. I’ve tried converting the .po file to latin-1 but same result on the conversion.
Any hint?
I think this is a fantastic lib, how can I help you in the debug?
Thanks a lot!
Don’t worry just figured out, the problem was that my po file it’s a very simple one, like this one:
msgid “Username”
msgstr “Nombre de usuario”
msgid “Password”
msgstr “Contraseña”
msgid “Login”
msgstr “Login”
Then I noticed on line 92 this code “case ‘#|’” where the key/data is added to the hash, I don’t have that char on my po file, so was never added, I’ve copied the same code from the case to line 139, and now it’s working greaaat!
Thanks a lot for this lib!
Best regards,
Esteban
Hey Esteban,
Thanks for posting and glad you got it sorted out! Let me know if there’s anything else I can help with, or if you have any suggestions/feedback.
Execellent job and post!!
Hey, after many hours of googling, I finally found someone who did a very great job for me.
Thanks a lot, it works perfectly by here. Keep up good work !
Dude, this is awesome! I’ve been struggling with Poedit for a long time, both on Windows and Mac. It’s simply feels alien inside my workflow, but automatizing this with this great lib is just two thumbs up.
… However, I’d love to see the lib report at least some error messages in case it’s necessary. Poedit often enough gave be the finger over nothing, and debugging was a pain – but at least I knew when something was wrong. I couldn’t tickle your lib to give me just any kind of output. As far as I can see, the only thing I get is a “true – all clear” or a “false – go check for yourself what went wrong”, right?
Interesting feedback and thanks for the comment.
I haven’t worked with this for a while, so I’d love it if you could share any solution you come up with! Feel free to do a pull request on github too.
Hey there, we’re writing a similar utility, and I noticed a couple small things in your code that could be problematic.
It appears to explode on spaces, which means that different whitespace might be parsed incorrectly.
The eval is statement is probably not a concern if you trust your POs, but since I’ve heard of people building this into wordpress plugins etc, it’s probably an unnecessary risk that should be worked around. Certain strings could execute nearly anything.
Cheers!
Hey, these sound like great catches. Are you able to make any changes or edits and submit them to the git repository? I’m pretty busy with other things right now!
No problem. I forked it, made a few changes and filed a pull request back to your project. Please double check me and pull if so inclined.
Cheers!