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);
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.