Localizing PHP Applications “The Right Way”, Part 1
New audiences around the world access the Internet every second, most of whom would be delighted to find your content in their mother tongue. You might think you only need a good translator to translate the user interface of your website, an easy task nowadays given how easy it is to find one, but the bigger challenge isn’t translating or writing multilingual content… it’s writing the code behind the scenes.
Localizing software applications in general used to be a cumbersome and error-prone task resulting in a lot of messy code. Some developers even use different versions of code for the same application but for different locales, which makes managing the codebase practically impossible. Enter gettext, the wonderful open-source tool that will make your life easier by allowing you to concentrate on your code. Localization becomes a matter of writing separate translation files for the target language, which can easily be done by a translator using Poedit. If you master gettext for PHP, you will find extending your application’s global reach really can be just a matter of translation!
In this series of articles you will learn how to gettext to localize your PHP application. Part 1 will provide just a quick foray into gettext. Each subsequent part will build on preceding parts, teaching you how to handle multiple translation domains, plural forms, and even how you can automate some of the localization process.
Preparing the Environment
I prefer to make sure my environment is set up properly before I start learning something new, since having everything up and running correctly makes it easier to test what I learn step-by-step. Here is a checklist of things you need to have installed before going any further:
- PHP 5.x on Apache (or whichever web server you prefer), with the gettext extension enabled. You can always get the latest PHP for your platform at www.php.net.
- Poedit, a cross-platform editor for gettext catalogs. It’s a really nice tool that lets you keep your translations separate from your application code. You can get a copy from www.poedit.net
Regardless of your platform, to use gettext from PHP you will need to have the gettext library installed and the PHP extension that hooks into the library.
Ubuntu/Debian users can use
apt-get and Fedora/CentOS/Redhat users can use
yum to install the gettext library. If you’re using another unix-like system, go to www.gnu.org/s/gettext and get a copy of gettext that is compatible with your platform. Windows users can download the latest executable and install it from gnuwin32.sourceforge.net/packages/gettext.htm.
After you install the library, you need to enable the PHP extension for gettext by editing
php.ini and adding a single line:
# for Windows users extension=php_gettext.dll # for *nix users extension=gettext.so
Then, install Poedit which will be used later. You can download a copy from www.poedit.net.
Hello World with gettext
In your web root directory, create a sandbox directory for playing with gettext named
TestI18N (I18N stands for Internationalization). Within the
TestI18N directory, create the following hierarchy:
In future projects, you can really name the parent directory and the
Locale directory any name you want, but
LC_MESSAGES are standard names which are used by gettext.
en_US stands for the name of the locale and is made up of two parts. The first part is a two-letter lowercase abbreviation for the language according to the ISO 639-1 specification. The second part after the underscore is a two-letter uppercase country code according to the ISO 3166-1 alpha-2 specification.
en_US thus means the language is English as spoken in the United States.
Next, make sure Poedit is working correctly on your platform. Launch the program and choose from the top menu bar
New Catalog. In the settings window, fill in the information below skipping the plural forms field for now:
OK and then save the file as
messages.po inside the
LC_MESSAGES directory you created earlier.
Now close Poedit, and use your favorite text editor to open
messages.po… yes, it is an ordinary text file! you can edit it by hand, but to save ourselves some hassle we let Poedit create the main definitions for us. Leave an empty line after the lines that are already in the file and add the following:
#Test token 1 msgid "HELLO_WORLD" msgstr "Hello World!" #Test token 2 msgid "TEST_TRANSLATION" msgstr "Testing translation..."
messages.po and close it, and then re-open it in Poedit.
In Poedit, choose
Save or click the Save Catalog entry in the icon bar. The reason we are saving the PO file in Poedit is because they need to be compiled into a special format usable by gettext. After you save it in Poedit, you will see a new file has been created in the same directory with the same name but with the extension
.mo. If you were to continue to modify and save the PO file with a regular text editor, you would need to compile it using the
pocompile command. The extra compilation step isn’t necessary if you use Poedit because it automatically compiles the file anytime you save it.
Back in the
TestI18N directory, create a file named
test-locale.php with the following code:
<?php // I18N support information here $language = "en_US"; putenv("LANG=" . $language); setlocale(LC_ALL, $language); // Set the text domain as "messages" $domain = "messages"; bindtextdomain($domain, "Locale"); bind_textdomain_codeset($domain, 'UTF-8'); textdomain($domain); echo _("HELLO_WORLD");
TestI18N/test-locale.php in your browser. If everything is installed correctly and working fine, you will see Hello World displayed on the page.
When it comes to localizing your PHP application, you may have a lot of options at your disposal. We chose to use the GNU gettext library and its PHP extension, a powerful and easy approach that localizes the application “The right way!” In this installment you saw what’s needed to install gettext and the PHP extension, briefly used Poedit, and whetted your appetite with a simple Hello World script. Part 2 will use this as a basis for learning more about gettext; I’ll explain each function introduced in the Hello World script as well as how the gettext library works.