Spiga

using Zend Framework Language component

by Gabi Solomon

Today i will continue the series of articles on the zend framework and i am going to talk about how i come to use the language component from zend.

The way i decided to go with it is by having a controller plugin that starts the language component and also detects the language.

But first thing first. We need to make the url to allow us to change the language. And to do that i added a new rule in the bootstrap file:

PHP:
  1. $route = new Zend_Controller_Router_Route(
  2.             ':language/:controller/:action/*',
  3.                 array(
  4.                     'language'   => 'en',
  5.                     'module'     => 'default',
  6.                     'controller' => 'index',
  7.                     'action'     => 'index'
  8.                 )
  9.             );
  10.         $router->addRoute('lang_default', $route);

This rule will produce urls like:

http://www.domain.com/en/controller/action

http://www.domain.com/es/controller/action

I decided to go with this type of URL instead of caching or storing the language in the session to not have google consider our pages as duplicate content. I have read that it better to go with subdomains (ex: http://en.domain.com/controller/action ) that with directories but for now i will do it this way.

Now that we are still in the bootstrapfile, we will also add our plugin:

PHP:
  1. Zend_Controller_Front::getInstance()->registerPlugin(new GSD_Controller_Plugin_Language());

ANd now for the final touch the plugin:

PHP:
  1. <?php
  2.  
  3.  
  4.  
  5. /**
  6. * Front Controller Plugin
  7. *
  8. * @uses       Zend_Controller_Plugin_Abstract
  9. * @category   GSD
  10. * @package    GSD_Controller
  11. * @subpackage Plugins
  12. */
  13. class GSD_Controller_Plugin_Language extends Zend_Controller_Plugin_Abstract
  14. {
  15.        
  16.     public function routeShutdown(Zend_Controller_Request_Abstract $request)
  17.     {
  18.        
  19.         $locale = new Zend_Locale();
  20.        
  21.         $options = array('scan' => Zend_Translate::LOCALE_FILENAME);
  22.         $translate = new Zend_Translate('gettext', Zend_Registry::get('siteRootDir') . '/application/languages/', 'auto', $options);
  23.        
  24.         $requestParams = $this->getRequest()->getParams();
  25.         $language = (isset($requestParams['language'])) ? $requestParams['language'] : false;
  26.                 if ($language == false) {
  27.                      $language = ($translate->isAvailable($locale->getLanguage())) ? $locale->getLanguage() : 'en';
  28.                 }   
  29.         if (!$translate->isAvailable($language)) {
  30.             throw new Zend_Controller_Action_Exception('This page dont exist',404);
  31.         } else {
  32.        $locale->setLocale($language);
  33.             $translate->setLocale($locale);
  34.             
  35.             Zend_Form::setDefaultTranslator($translate);                                
  36.    
  37.            
  38.             setcookie('lang', $locale->getLanguage(), null, '/');
  39.             
  40.             Zend_Registry::set('Zend_Locale', $locale);
  41.             Zend_Registry::set('Zend_Translate', $translate);
  42.         }
  43.     }
  44. }

A few explanations on the code.
I am using gettext adapter with auto mode ... witch will basically crawl the language directory to detect what languages can you support. I also use it conjunction with Zend Locale and at the end i store the in the Registry.
Storing Zend translate in the registry will enable you to use it in the view in a very easy way using a built in helper.

Using translate in you controllers

PHP:
  1. $this->view->title = $this->view->translate('default-register-index-title');

Using translate in you views

PHP:
  1. <?php echo $this->translate('default-register-index-title'); ?>

As a note i am not using the full text for translate i am using keys that have a naming conventions like "module-controller-action-message". I find it much more easier then putting the whole string and also much more easier to maintain. Imagine if you misspelled a string, or want to modify it ? you will then have to modify it every in your code.

That is basically it.
Cheers

Update:
I have also published this plugin on phpclasses, you can find it here.

Related Posts

  • It is good and very usefoul for us. We must now use it. thanks
  • Thanks that you offer that tips but i can use it because i dont know how. Thanks anyway
  • It is interesting but it is hard to implement it.
  • thank's for sharing this!it'a great post!
  • thank's for sharing this!it'a great post!
  • Well worth the read. Thanks for sharing this information. I got a chance to know about this.
  • Very good aproach!
  • @dantan how are you building your routes ?
    maybe your not using the lang route i described
  • dantan
    Works good so far.
    Using the Url view helper I have good links, IndexController and IndexAction are filtered. But I still have links with the default module inside e.g. /en/default/login instead of /en/login.

    Maybe you have a simple idea hot to get rid of the "default" when not needed.
  • Betty
    Gabi, thanks again, your second suggestion works, but now I had to put in every link language => xx.

    About the first one (save the language in a session or cookie to be sure that it remembers it.), at the moment I don't find it necessary to remember the language in a session.

    But how do I change the current url to the same but with different language:
    EN/contact should change to DE/contact.
    (I don't know how to do that with dynamic urls)

    Thanks again!
  • you can make a custom route class and save the language in a session or cookie to be sure that it remembers it.

    and for the second question:
    $this->url(array('language' => 'DE'), 'our-service');
  • hello, i read this site and i think it is good idea!
  • Betty
    @Gabi Solomon

    Right, I just found out:
    url ([array $urlOptions = array()], [mixed $name = null], [boolean $reset = false], [boolean $encode = true])

    $reset should be false.

    But this does not work for following:
    //our-service
    $route = new Zend_Controller_Router_Route(
    ':language/our-service/',
    array(
    'language' => 'en',
    'module' => 'default',
    'controller' => 'index',
    'action' => 'our-service'
    )
    );
    $router->addRoute('our-service', $route);

    $this->url(array(), 'our-service', false)

    Language stays EN even when I ask for DE/our-service.

    For all other links I use the default router.


    And another question, how could I define an url to stay with same url, but just change the language?

    For example, EN/contact should change to DE/contact.


    Thanks for your help!
  • @betty
    if you use the url view helper .. they should be automaticly generated
  • Betty
    Thanks for the info.

    What do I need to do so that url's () on a webpage are automatically like:
    EN/module/controller/action or
    DE/module/controller/action

    depending on the active language?

    At the moment all url's start with EN.
  • @Jani Hartikainen
    Thanks for the advice. I added the language detection.
    I will try to make time to modify it to take params.
  • A good, although not perfect, approach =)

    It would be better if you made the plugin configurable, so that you could define the translation sources easily rather than having to edit the code of the plugin.

    Another thing is that it might be a good idea to attempt detecting the user's own language from their browser, if no other language is found. I recall Zend_Locale can do that for you.
blog comments powered by Disqus