Localize your site in 3 easy steps

November 22, 2007 – 11:03 am Tags: , ,

Internationalization and localization means making your site usable in more than one languages. Well, to be honest, you could call a site that’s only in english localized to english visitors too, but in any case…

These two are also known as I18N and L10N. Can you guess where these acronyms come from? The first and last letter from each word and then the number of letters between… Someone’s been feeling really creative ;)

While PHP has an extension for GNU Gettext, which can be used for localization, it isn’t the easiest thing to use. Additionally, PHP can also do number and money formatting based on the locale, but this depends on the server: You must have the locale installed on it. On Shared Hosting accounts, some locales may be unavailable and you may not be able to install them. Not to mention that gettext can be a bit of a hassle to get working.

So, rather than using PHP’s native support, why not use Zend Framework’s Zend_Locale and Zend_Translate?

Step 0: Start

In the fashion of for-loops, the first step shall be 0. Anyway, let’s start.

So, the first thing we need to do is define a new Zend_Translate object. This is the class which handles the translation stuffs.

The Translate class takes an adapter as the first parameter. You can use different kinds of adapters, which is very useful: For example, you can use the array-adapter for testing things as it’s very easy to work with. Then, you can later move to one of the XML based formats or the gettext format, just by switching the adapter and the parameters.

We’ll just use the array-adapter now to keep things simple. There’s more info on the adapters at the Zend Translate manual page.

$translate = new Zend_Translate('array',array(),'en_EN');

Here we define a new translate object, with ‘array’ as the adapter and an empty array as the translation list for language ‘en_EN’. But why an empty list? We’ll get to that in a bit.



Now that we have the translate object, how do we actually output content with it?

echo $translate->_('Hello World');

Easy, eh? And here’s why we gave an empty array for the english language: Zend_Translate will output the text shown here, if there is no translation available. Thus, if we write the messages in english, we won’t need to add anything to the english array.

Step 1: Adding a language

Now, let’s add an another language. I’m going to add finnish:

$translate = new Zend_Translate('array',array(),'en_EN');
 
$fi = array(
         'Hello World' => 'Hei Maailma'
       );
 
$translate->addTranslation($fi,'fi_FI');

Now we have a finnish translation for Hello World: Hei Maailma. We can change the language the script will output with the setLocale command:

$translate->setLocale('fi_FI');
echo $translate->_('Hello World'); 
//Output: Hei Maailma

Step 2: Letting the user choose a language

Now that we have some languages to use, let’s give the user the possibility of viewing the page in their own language.

As I mentioned in The Mythical HTTP Protocol, the HTTP request carries some information from the user: Their browsing language.

Zend Framework provides us with a nice and easy way of detecting which language the user’s browser is configured to use: The Zend_Locale class. The Zend_Locale class can be used in some locale-aware classes in ZF to configure which locale settings the class will use. This includes Zend_Translate.

//By default, the locale will be detected from the user's browser.
$locale = new Zend_Locale();
 
//Check if the locale is available
if($translate->isAvailable($locale))
    $translate->setLocale($locale);

Pretty simple again. We simply create a new locale object and check if there’s an available translation and change the locale. The check is necessary, because the user might be using some locale we don’t have a translation available for and if we try changing the translation’s locale to that, we will get an error.

But what if the user’s browser is configured to use some other language than the one the user prefers? In that case, we should provide some links for the user that they can click to change their language.

The simplest way to do this is to make the link take the user to a page which will store their desired language in a cookie. Then we can use the cookie to detect the default locale the user wishes to use:

$localeCookie = (isset($_COOKIE['lang']))
              ? $_COOKIE['lang']
              : null;
 
$locale = new Zend_Locale($localeCookie);
if($translate->isAvailable($locale))
    $translate->setLocale($locale);

Conclusion

Making a locale-aware site with the Zend Framework is very easy. All you need is the Zend_Translate and Zend_Locale classes and some imagination… and preferably someone to translate your site, too!

Here’s the full code for the examples:

//Create default english translation
$translate = new Zend_Translate('array',array(),'en_EN');
 
//Create a finnish translation
$fi = array(
         'Hello World' => 'Hei Maailma'
       );
 
//Add it
$translate->addTranslation($fi,'fi_FI');
 
//Detect if the user has chosen a different language
$localeCookie = (isset($_COOKIE['lang']))
              ? $_COOKIE['lang']
              : null;
 
//Initialize the locale
$locale = new Zend_Locale($localeCookie);
 
//Change language if available
if($translate->isAvailable($locale))
    $translate->setLocale($locale);

You can use the $translate variable in your view scripts, too. Just assign it to the view and you’re on your way to localizing your view scripts.

The Zend_Locale class has also some other uses, such as number formatting. You can read more about it in the Zend_Locale manual pages.

Share this:

RSS feed Subscribe to my RSS feed

About the author

Jani is a 15 year veteran of the software industry. He's currently available for consulting

  1. 12 Responses to “Localize your site in 3 easy steps”

  2. Yeap… it’s good…
    but you have forgot about content translation wich is stored at DB… this case we need modify DB structure to group translateable fields at separate table… or may be you have another solution?

    By iDownload on Dec 1, 2007

  3. Yes exactly, iDownload.
    This question is very interesting.

    By dino on Dec 12, 2007

  4. DB translation is something a bit more complex in ZF as I don’t recall it having a DB adapter for Zend_Translate, so you’d have to write it yourself.

    Storing translations in DB should be relatively simple in my opinion.

    You could basically have a table like this: id, original, locale, translation

    “original” would be the word which appears in Zend_Translate calls, locale would be the language, ie. en_EN and translation would be the translation in the target language.

    By Jani Hartikainen on Dec 12, 2007

  5. One thing you didn’t mention is how to set the cookie to the user’s desired language. Can you add that to your post? Thanks!

    By Amit on Aug 22, 2008

  6. You would use PHP’s setcookie() function to store the language identifier.

    By Jani Hartikainen on Aug 22, 2008

  7. Seems in newer Zend Framework versions, you need to have at least one translation. So if you run into weird errors when doing

    $translate = new Zend_Translate(‘array’,array(),’en_EN’);

    Just modify the empty array to contain something.

    By Jani Hartikainen on Oct 6, 2008

  8. Hi jani, thanks for this article really helped me understand how Zend_Translate works.

    I have a question about passing the language through the URL, I don’t know what exactly to use for this I tried zend_route but its more for forwarding aliases to url’s I don’t know how can i add the language in the URL, please advice

    thanks

    By Mo on Mar 24, 2009

  9. You could use a route: just create one which takes an additional parameter for language, say something like ‘:lang/:controller/:action’ or such. Then, you can create a controller plugin which determines the language and sets up the locale/translation.

    You could also use a GET parameter, like ?lang=en

    By Jani Hartikainen on Mar 28, 2009

  10. Hi.. Very usefull your article for me, starting ZF.

    I implemented it, but how I add a link in any place to change between languages.

    By Zedl on Apr 16, 2010

  11. Hi,

    Is it normal, that Zend takes the last added/initialised language as the defaut language if nothing is set or specified?

    Also, you should pass something in the 2nd parameter (array) at:
    $translate = new Zend_Translate(‘array’,array(),’en_EN’);

    otherwise youll get (i do) an notice like:

    Notice: The language ‘en’ has to be added before it can be used. in path/Zend/Translate/Adapter.php on line 430 Notice: No translation for the language ‘en’ available. in path/Zend/Translate/Adapter.php on line 443

    By pascal on Sep 23, 2011

  12. there’s array(‘disableNotices’ => true) for using as a 4th parameter but that seems somehow not nice. hmm

    By pascal on Sep 23, 2011

  13. hi

    how can i save the user selected language in cookie and how i must build this in my view / code to get the language switch?

    also in my view, im must build 2 links for english and russia for example.
    but should i link to a controller or should i catch the lang switch in a plugin?

    can somebody give me a example?

    and, in the cookie example above, there is “lang” stored in the cookie.
    but some countries has 2 languages. canada for example.
    “fr” and “en”.

    why would be stored the lang and not the locale?
    what is the reason for this?

    By Klaus on Jun 20, 2012

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)