Zend_Navigation et site multi-langues

Published by Pierre-Auguste on 28 Avril 2009 - 11:59pm

Il m'a fallut un petit moment pour comprendre comment créer une route efficace pour gérer mes sites multi-langues. Le grand problème a été la venue de Zend_Navigation qui ne comprenait pas mon ancien système. Je ne pouvais pas créer un menu dans la langue consultée car il me renvoyait chaque fois à la langue par défaut du système.

Voici donc une nouvelle solution qui fonctionne bien.

Dans un premier temps, nous devons créer un plugin pour notre controller principal :

class My_Controller_Plugins_Language extends Zend_Controller_Plugin_Abstract
{
protected $languages = array('en','fr','de','it','es');

private $_lang = 'en';

public function routeShutdown(Zend_Controller_Request_Abstract $request)
{
if (!$lang = $this->getRequest()->getParam('sys-language'))
{
$lang = $this->getBrowserLanguage();
}

$locale = new Zend_Locale($lang);
Zend_Registry::set('Zend_Locale',$locale);

$route = Zend_Controller_Front::getInstance()->getRouter();
$route->setGlobalParam('sys-language',$locale->getLanguage());
}

public function getBrowserLanguage()
{
$langs = Zend_Locale::getBrowser();

foreach ($langs as $lang => $pref)
{
if (in_array(substr($lang,0,2), $this->languages))
{
return $lang;
}
}
return $this->_lang;
}
}

Je vous laisse consulter la doc concernant le routage si vous voulez en savoir plus. Le script ci-dessus surcharge la fonction routeShutdown() car je veux agir en "sortie" de routage. Il va récupérer la langue passée dans l'URL (/fr/...) et vérifie que celle-ci est valide. Si ce n'est pas le cas ou si la langue n'est pas définie à ce stade, pour la page d'index par exemple, alors la fonction getBrowserLanguage() s'occupe d'aller récupérer les langues acceptées pas le navigateur et les compare avec les langues acceptées par le site, puis fourni la langue du système.

A ce stade la langue du système est connue alors j'en profite pour paramétrer les locales du système et les inscrire dans le registre.

Ce qui manquait à Zend_Navigation, c'est la route par défaut qui devait changer selon la langue du système. La fonction $route->setGlobalParam('sys-language',$locale->getLanguage()); fait ce travail et ainsi le menu se reconstruit juste selon la langue consultée.

Pour que tout ceci fonctionne, nous devons annoncer ce plugin à notre controller et créer la route dans le bootstap :

$frontController = Zend_Controller_Front::getInstance();
$frontController->registerPlugin(new My_Controller_Plugins_Language());
$frontController ->addModuleDirectory($my_path_to_the_modules);
$router = $frontController->getRouter(); $router->addRoute('default', new Zend_Controller_Router_Route('/:sys-language/:module/:controller/:action/*', array('module'=>'default','controller'=>'index','action'=>'index'), array('sys-language'=>'en|fr|de|it|es'));

Il est important de nommer cette route "default" ( $router->addRoute('default',...) ) à moins que vous ne sachiez ce que vous faites au rique de vous retrouver en dehors des sentiers battus et de vous perdre ! ;)

Maintenant vous devez vous servir du helper de vue $view->url() pour générer tous les liens (même dans vos formulaires !).

Sur toutes les pages, vous pouvez créer un lien vers cette même page mais dans une autre langue comme ceci :

<a href="<?php echo $this->url(array('sys-language'=>'en')); ?>">English</a>
<a href="<?php echo $this->url(array('sys-language'=>'fr')); ?>">French</a>

Dernière étape pas encore réalisée, c'est de générer une sitemap avec toutes les langues, mais ça c'est une autre aventure...

Commentaires

Portrait de Pierre-Auguste

La version du Zend_Framework que j'utilise est la 1.8.0beta... je donnerai les explications concernant Zend_Navigation quand la version stable sortira.