
<?php
if (!extension_loaded('gettext')) {
//in Windows extensions are .dll files, Unix .so!
if (!dl('gettext.so')) {
//no way...you don't have gettext!
exit;
}
}
?>
If the extension is not available don't dispair, you can still use this, but in that case this guide won't be of much help anymore.
Otherwise, keep reading...
Second step: preparing the environment (I)
This might be the most difficult step, because it will completly depend on your server configuration (win/unix, compilation options, php version).
I have come up with a simple procedure that is cross-os working, but if you are on Unix server there is an additional note.
Extra step (unix users): checking your locale.alias
It looks like that the function setlocale() might not accept a language code that is not listed in the locale.alias file. This file contents all the reference names to the Unix machine locale names: examples are "it_IT","en_US","it_IT.utf8.euro".
You can check the file content firing up the console or through a ssh session:
cat /usr/share/locale/locale.alias
Or, through a PHP script:
<?php
//note: your hosting service might still prevent you to execute code...
echo exec('cat /usr/share/locale/locale.alias');
?>
As in this case we are talking about string translation, and not about time or currency translation (using for example the strftime() in PHP), the name of the locale we will use doesn't need to be the actual language of the strings. In fact, you might not find a language string you need in this file (e.g. "italian"), but you will also find many other langauage codes that most propbably you won't use (e.g. "thai"). In this case you can use setlocale("thai") to store Italian language strings. In a hosting service for example I found the locale "slovak", but not "english", so in my PHP script, I use the var $lang as "slovak" to actually point to English strings.
Or a lot better would be if you can just modify your locale.alias file - but most probably your hosting service won't let you do that.
Second step: preparing the environment (II)
Now we are finally ready to start:
<?php
//depending on your php configuration, LC_MESSAGES constant might be not defined, so we define it with it's standard value
if (!defined('LC_MESSAGES')) define('LC_MESSAGES', 6);
//our string files directories
define(BASE_DIR, realpath('./'));
define(LOCALE_DIR, BASE_DIR .'/lang/');
$encoding = 'ISO-8859-1'; //case sensitive!
$domain="messages"; //case sensitive!
$lang="it_IT"; //case sensitive!
putenv("LANGUAGE=$lang");
setlocale(LC_MESSAGES,$lang);
bindtextdomain($domain, LOCALE_DIR);
//only available since PHP 4.2
if(function_exists("bind_textdomain_codeset"))
bind_textdomain_codeset($domain, $encoding);
textdomain($domain);
?>
The constant LOCALE_DIR is the location of the language definitions files. The structure is simple:
LOCALE_DIR/$lang/LC_MESSAGES/$domain.po
<?php
//after the code we previously prepared
//if you are windows user, use the "" inside the function, not ''. Read over to know why.
echo _("Test translation");
//a correct usaga of _() when we need to show variables is sprintf
$items="10";
echo sprintf(_("There are %s items in the box"),$items);
?>
All the strings we will translate must be inside the function _(), but we can define also wrappers with any name:
<?php
function T_($s){
return _($s);
}
?>
Running this example will just print out "Test translation". And this means everything is just fine. But how do we translate it to other 100 languages? We need to create our strings definition files. How do we do that? We need external tools.
This time, if you are windows user, you will find some more job to do. In windows we will need to install the gettext executables available out of the box in unix systems. The easiest way is as follows:
- get the msys installer and install the package;
- get the gettext fow win32 and install it;
Now if you have done everything right you should have a bin folder in msys with the gettext executables (otherwise just move them in)
From here on Win and Unix system are about the same.
Fire up your command prompt/bash, change to your php project directory and
//Win
c:\msys\bin\xgettext.exe --default-domain=messages -k_ --output=lang/it_IT/LC_MESSAGES/messages.po test.php page2.php ...
//Unix
xgettext --from-code=iso-8859-1 -Lphp --default-domain=messages -k_ --output=lang/it_IT/LC_MESSAGES/messages.po test.php page2.php ...
You will need to change paths accordingly to your system, and at the end of the command list the files you need to translate.
Some explanation:
--default-domain must be the same as specified in the $domain var in php, and the .po filename should have the same name.
-k will tell gettext what is the magic function he should look for - if you use a wrapper like in our example change this to -kT_
-L will tell gettext what programming language of the file is PHP. Note that in Win is not used, because the gettext binary is kind of old,
and it won't recognize PHP, so it will fallback to C. That's why you should use _("") rather than _('').
--from-code is the char encoding of our source files.
To check if everything was ok, just open the .po files with any text editor. You should see your strings taken from the PHP files.
Final step: translating
From here on you will just need to translate your strings using an editor, get the .mo file, put it in the proper language folder, and call the
php script just changing our $lang variable.
Tools to translate and how to do that is explained in depth by Wordpress Codex here.
In this article we have created .po files instead .pot as in Wordpress, but you can use .po files as well.
Even thou the startup sounds difficult, once you have set up your system you will find amazingly easy to translate to as many languages as you can,
because you can first code your page in your own language, and then translate it, without the need of creating huge arrays and thinking of hundreds of var names to identify your strings.
Added by Roberto on September-20-2007, 1:23 am
