PHP i18n Internationalization Tutorial

 PHP i18n Internationalization Tutorial  

This tutorial will guide you through the way to make your application internationalized and be multilingual. It is already been used in wide range successfully for WordPress’s multi language support feature. You should know prior that, debugging this feature is quite hard in php as it won’t show any error/warning or notice message for any kind of failure. So it is up to you to check all and set them up right way. I will try to explain the different issues you will might need to consider to get it working properly.

PHP Prerequisites:

Basically only restriction from PHP side is that you need to have the ‘gettext‘ module installed. If you are using a development bundle like MAMP, XAMPP etc, you should have them already set up by default. You can check it by seeing the output of ‘phpinfo()’ and see if ‘gettext’ module is enabled. In case you don’t have it installed, specially for manual php installation, you will need to re-compile and build your php distribution, as described in gettext documentation.

Basic PHP Environment Setup:

The base php code for the set up is as below:

function setLocalization($code) {
    $langCodes = array(
                         "de" => "de_DE",
                         "fr" => "fr_FR"
    if(!isset($langCodes[strtolower($code)])) {
    $baseLangDir = './includes/locale';
    $appName     = "myapp";
    $lang = $langCodes[strtolower($code)];
    // Set language
    setlocale(LC_ALL, $lang);
    // Specify the location of the translation tables
    bindtextdomain($appName, realpath($baseLangDir));
    bind_textdomain_codeset($appName, 'UTF-8');
    // Choose domain

As you can see above, most of the codes are straight forward. However, you will need to focus on each section very carefully.

Most important is the language file path. To support a language, there need to be a .mo language file(will describe about it later) in a specific path relative to the ‘$baseLangDir’ as mentioned above. It need to be in “{$lang}/LC_MESSAGES/{$appName}.mo” format.

for ‘putenv’ function, sometime it will work for other environment variable like “LANG” too, you can try around if you are facing issue on this part.

Also, you should make sure that “setlocale(LC_ALL, $lang)” function is working properly by checking that its return value is same as the given locale. Otherwise you might have something wrong with your system locale setting.(described more later)

‘bindtextdomain’ will set the path from where the language files will be used. So, naturally we will feed the base directory path to it. ‘bind_textdomain_codese’ is important for setting the actual encoding format. You also need to be consistent about it with other section like creating po/mo file etc and make sure they in same encoding too.

Usage Of Language Text On Web Page:

Now, to make a text converted using this feature, we need to change any static texts on a webpage to use the php ‘gettext’ method as below:

<h2><?php gettext("This is a internationalized heading"); ?></h2>
<!-- OR -->
<h2><?php _("This is a internationalized heading"); ?></h2>

Get Your .mo File?

Now can’t check whether the above code is working? Because you don’t have a .mo file? Lets get this done then. First, we will need to generate .po file, which will include all translatable texts from your webpage. You can do it by a terminal command as below:

xgettext --default-domain=myapp -p ./locale --from-code=UTF-8 -n --omit-header -L PHP /path-to-templates/*.php

This will generate a myapp.po file for us, which will include all the texts wrppaed by php ‘gettext()’ method.

However, for your convenience, you can use the following po file as well as demo instead of above procedure:

# This file is distributed under the same license as the PACKAGE package.
msgid ""
msgstr ""
"Project-Id-Version: myapp\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-02-18 00:46-0500\n"
"PO-Revision-Date: 2014-02-26 12:31-0500\n"
"Last-Translator: Md Ali Ahsan Rana <>\n"
"Language-Team: LANGUAGE <>\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.4\n"

#: b4/89/60fe05fdf72a1cffc2aa1d43cb9cad6474e5aef6f36702c04c1498be890c.php:27
msgid "PHP i18n Internationalization Tutorial"
msgstr "Tutoriel internationalisation i18n de PHP"

#: b4/89/60fe05fdf72a1cffc2aa1d43cb9cad6474e5aef6f36702c04c1498be890c.php:63
#: b4/89/60fe05fdf72a1cffc2aa1d43cb9cad6474e5aef6f36702c04c1498be890c.php:77
msgid "Hello World"
msgstr "Bonjour tout le monde"

Now, to make the translation and generate the mo file, you can use several ways. The poedit tool will generate it automatically when you add translations and save. Otherwise, you can use the ‘msgfmt’ command line utility as below:

msgfmt -cv -o myapp.po

Also, if you want to do it programmatically, You can use third party php code like msgfmt-functions or something similar to do so as well.

Use separate po file for each language file and make sure that the language code is mentioned properly.

So, now after generating the mo file, you should be able to test the functionality completely. If you are using my given po file file(which is for french language), you should test with code as below:

echo gettext("Hello World");

Is it working now? Great then. In case its still showing issue, and seems your ‘setlocale’ function isn’t showing anything, you should checkout the next section as well.

Checking System Locale:

Though on my mac, I did able to get all functionality working properly, in a vagrant based centos development environment, I did face issue, which was related to system locale. The problem was, system didn’t have any other locale than english set up. I did able to fix it by using the following commands:

$cd /usr/share/i18n/locales/
$sudo localedef -c -i de_DE -f UTF-8 /usr/share/locale/de_DE
$cd /usr/share/locale/
$sudo localedef --add-to-archive de_DE
$sudo localedef --list-archive

Final Words:

Hope this tutorial on PHP i18n internationalization tutorial will be helpful to your way to make your application be an efficient multilingual. If you are having any issue on any section, don’t hesitate to ask me via comments. Happy coding :)


    • says

      Thanks for your comment. I already mentioned about the desktop poedit tool already, which definitely do the work, but can’t automate the process. Not sure about this site, can it help in automation? like extract data, translate and give back the mo file?

  1. Patrix says

    Hi! I have used the tool POEditor and I can tell you this about how it works: after creating the account, you create a project, import the .po file (or another supported format), translate the strings (just text, no code) by yourself or by collaborating with others (this is a big plus in contrast with a desktop tool like Poedit), and then, when the translation is done, export the file in any format you like that is supported (.mo included).
    Besides giving the obvious ability to manage a collaborative translation project, POEditor has other functions that help automate the software translation process, like Automatic Translation (provided by Bing/Google machine translation engines), Translation Memory and API.

Leave a Reply