Internationalisation with Zend_Framework

I’m loving discovering all these other parts of Zend Framework that I haven’t looked at yet. Today it was setting the locale of the application, and dishing out content specific to that region. Okay, lets get cracking.

In the root of the application, create /languages

And in there, create files like messages.es.php & messages.fr.php and messages.en_US.php. For English, as well as having en_GB and en_US, we should also have just en as a fallback. In these files, you put your translations in a big ass array:

<?php
return array(
  'nav-home'             => 'Inicio',
  'nav-services'         => 'Servicios',
  'nav-catalogue'         => 'Catálogo',
  'nav-contact'         => 'Contacto',
  'welcome'         => 'Bienvenido',
  'form-name'         => 'Nombre:',
  'form-email-address' => 'email:',
  'form-message'       => 'Mensaje:',
  'form-verification'  => 'verificación:',
  'form-send-message'  => 'Enviar',
  'form-title'         => 'Contacto',
);

Then you initialise the locale stuff in your bootstrap. If it can’t detect the locale from your browser then it will fall back to your default locale of choice :

protected function _initLocale()
{
    try 
    {
      $locale = new Zend_Locale('browser');
    } 
    catch (Zend_Locale_Exception $e) 
    {
      $locale = new Zend_Locale('en_GB');
    }
    $registry = Zend_Registry::getInstance();
    $registry->set('Zend_Locale', $locale);
}

To test the different locales, we can edit the bootstrap replacing the word browser for fr or es or en_US etc. But before we do that, a couple more things. First, initialise the translate stuff in the bootstrap too.

protected function _initTranslate()
{
    $translate = new Zend_Translate('array',
                  APPLICATION_PATH . '/../languages/',
                  null,
                  array('scan' => Zend_Translate::LOCALE_FILENAME,
                        'disableNotices' => 1));
    $registry = Zend_Registry::getInstance();
    $registry->set('Zend_Translate', $translate);
}

In the controller actions where you want anything to happen you get it from the Zend_Registry:

    $registry = Zend_Registry::getInstance();
    $this->view->locale = $registry->get('Zend_Locale');

Finally, you need to edit the nav links and the form field labels like so:

    <a href="blah"><?php echo $this->translate('nav-catalogue');?></a>

And the form:

    $email->setLabel('form-email-address');

Zend_Form is groovy enough to check for translations automatically, so that’s it really! A lot of fuss taken care of quite simply!

Another point is that now we have a locale, we can get locale specific versions of things like dates, currency, and number formatting. As an example:

echo $this->escape(
    Zend_Locale_Format::toNumber
    (
        $this->product->price,
        array
        ( 
            'locale' => $this->locale,
            'precision' => 2
        ) 
    )
);

And for a date:

    <?php echo $this->escape($this->productdate->get(Zend_Date::DATE_FULL)); ?>

As you can see this is easy and fun! So it would be awesome to have the ability to switch between them, yes? So lets make a locale controller:

class LocaleController extends Zend_Controller_Action

{

public function setAction()
 {
    // if supported locale, add to session
    if (Zend_Validate::is($this->getRequest()->getParam('locale'), 'InArray',
        array('haystack' => array('en_US', 'en_GB', 'de_DE', 'fr_FR')))) 
    {
      $session = new Zend_Session_Namespace('ttb.l10n');
      $session->locale = $this->getRequest()->getParam('locale');
    }
    // redirect to requesting URL
    $url = $this->getRequest()->getServer('HTTP_REFERER');
    $this->_redirect($url);
 } 
}

edit the _initLocale method in the bootstrap

  protected function _initLocale()
  {
     $session = new Zend_Session_Namespace('ttb.l10n');
     if ($session->locale) 
     {
        $locale = new Zend_Locale($session->locale);
     }
     if ($locale === null) 
     {
        try 
        {
            $locale = new Zend_Locale('browser');
        } 
        catch (Zend_Locale_Exception $e) 
        {
          $locale = new Zend_Locale('en_GB');
        }
     }
     $registry = Zend_Registry::getInstance();
     $registry->set('Zend_Locale', $locale);
  }

And then make some links in your layout to swap locales:

<a href="/locale/set/fr_FR"><img src="/img/locale/france-flag.png" />

Awesome! switching locales is a dawdle! Now to get on with my Spanish lessons some more! Adios!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s