Today it’s easy to make business with other country and to join the most poeple as possible, our website must be translated in many language. This tutorial will show you how to integrate multi-language into your URL with Zend Framework controller route component and be able to use it with the Url helper in your layout.
This tutorial requiere Zend Framework 1.8.2 version or higher.
Summary :
Route configuration
This tutorial will show you how to setup your route in .ini config. But you can do it with any other configuration type. The demonstration will also use the Module structure of Zend Framework.
Here we setup the default module route without any parameters because it will automatically use the Dispatcher to setup it. Note the abstract param. This part is not actually documented in the ZF Programmer’s reference guide but Abstract parameter make the route to be unusable outside a chain route.
1 2 3 | resources.router.routes.defaultmodule.type = Zend_Controller_Router_Route_Module resources.router.routes.defaultmodule.abstract = On resources.router.routes.defaultmodule.defaults.module = "system" |
After we setup the language route with default language if you need it and the regex of what is expected for the language value.
4 5 6 7 | resources.router.routes.language.type = Zend_Controller_Router_Route resources.router.routes.language.route = ":language" resources.router.routes.language.reqs.language = "^(fr|en)$" resources.router.routes.language.defaults.language = "en" |
Than we setup the default route to overwrite the one create by default by the Front Controller.
8 9 | resources.router.routes.default.type = Zend_Controller_Router_Route_Chain resources.router.routes.default.chain = "language, defaultmodule" |
This configuration mean that if you call url like http://www.exemple.com/, language will be English, module will be default, controller will be index and action will be index.
If you call http://www.exemple.com/fr/articles , language will be french, and module will be articles.
Dont forgot to setup your locale and translate resources!
Multilanguage Plugin
In this part I will explain how to create your multilanguage plugin for controller. I assume here you know how to setup your Controller plugin into your Front Controller and pass directly to the Plugin class. It’s very basic and you will have to adapte to your own use.
Create a new class in your own library componant with routeShutdown method.
1 2 3 4 5 6 7 8 9 10 11 | class My_Controller_Plugin_Multilanguage extends Zend_Controller_Plugin_Abstract{ public function routeStartup (Zend_Controller_Request_Abstract $request) { } public function routeShutdown (Zend_Controller_Request_Abstract $request) { } } |
In the routeStartup method, we add a quick fix to be sure the language is alway in each RequestUri. If the language parameter is not there, we force it.
1 2 3 4 | if (substr($request->getRequestUri(), 0, -1) == $request->getBaseUrl()){ $request->setRequestUri($request->getRequestUri()."en"."/"); $request->setParam("language", "en"); } |
In the routeShutdown method you will catch the language and setup the local and translator object already created by the resource. After you setup the translator to the Zend_Controller_Router_Route. This will be something like this :
1 2 3 4 5 6 | $language = $request->getParam("language", Zend_Registry::getInstance()->Zend_Locale->getLanguage()); $locale = new Zend_Locale($language); Zend_Registry::getInstance()->Zend_Locale->setLocale($locale); $translate = Zend_Registry::getInstance()->Zend_Translate; $translate->getAdapter()->setLocale(Zend_Registry::getInstance()->Zend_Locale); Zend_Controller_Router_Route::setDefaultTranslator($translate); |
Once it done. Url helper will be very easy to use.
Url Helper howto
Ok, here if you have lot of route setup, you will need the $currentRoute parameter in your url helper. If you play only with the default route, you don’t need the following part. Jump to the next step.
1 2 3 4 5 | $front = Zend_Controller_Front::getInstance(); $router = Zend_Controller_Front::getInstance()->getRouter(); $currentRoute = $router->getCurrentRouteName(); $locale = $this->registry->Zend_Locale; $currentRoute = ($currentRoute == "language")? "default": $currentRoute; |
In the last part, I show you a basic Language Switch I did for my project. It check the current language and dont show the link of the current language.
See the Zend_View_Helper_Url parameter. If I dont put the language param in the array, it will show the current one. This link will switch between the same page but in different language.
1 2 3 4 | <div id="langswitch"> <?php if ($locale->getLanguage() != "fr"):?><a href="<?=$this->url(array("language" => "fr"), $currentRoute)?>">Francais</a><?php endif?> <?php if ($locale->getLanguage() != "en"):?><a href="<?=$this->url(array("language" => "en"), $currentRoute)?>">English</a><?php endif?> </div> |
An other example that will output http://www.exemple.com/fr/articles/
1 | <a href="<?=$this->url(array("language" => "fr", "module" =>"articles", "action"=>"list"), "default")?>">Module Articles</a> |
Conclusion
This example is take from my current PhenixApp project. All my source can be found in the repository. The code on my repository is not the same because I had more option like I take my default language from the database and I have some other route that I have to work with.
With the code in this tutorial, you get a working and easy multilanguage URL. You can integrate it very fast to your existing project because it use chain routing and dont broke any other route already exist.
If you like this tutorial or want to improve it, you can add comment.
Tags: config, controller plugin, default controller, default language, default route, demonstration, dispatcher, language, language resources, module resource, module structure, parameters, reference guide, resource, router, translate, translation, Zend Framework
Related posts:
- Autocomplete field with Zend Framework and Dojo
- How to use Flickr with Zend Framework?
- Phenix_Wiki, a parser componant for Zend Framework
Tags: config, controller plugin, default controller, default language, default route, demonstration, dispatcher, language, language resources, module resource, module structure, parameters, reference guide, resource, router, translate, translation, Zend Framework
[...] can go see my small tutorial on language routing. M4d3L-Network Blog Add language route to your Zend Framework project. Then change the chain route to be apply to hostname else to the Request [...]
Bonjour,
Ton travail est intéressant , cela dit , ça ne fonctionne pas. le routeur confond la langue et le controller.
exemple : Uncaught exception ‘Zend_Controller_Dispatcher_Exception’ with message ‘Invalid controller specified (en)’
Svp aide moi,
Désolé pour mon message en français j’éspère que tu as quelques connaissances en français
Oui je parle francais bien sur
c’est ma langue maternelle! C’est plutôt mon anglais qui fait un peu pitier hehe!
Pour ton problème, a tu bien mis tes routes autre que « default » et language abstract?
Sinon peu tu me copier ta configuration de route sur past2.org et le linker ici? Ou encore tu peux venir discuter avec moi sur IRC #FREENODE. je traine sur #ZFTALK et #ZFTALK-FR.
I get this error: Fatal error: Call to a member function getLanguage() on a non-object in … /Controller/Plugin/LangRoute.php on line 14. Any ideas??
Can you paste your code on paste2.org and link it in your comment to help me to see what you are doing wrong?
thank.
Just through other readers my like to know, Zend_Controller_Router_Route_Chain
used like this needs ZF 1.8 or grater
Great tutorial!!!!
But
I can also translate the name of the controller/action?
example:
must go on the same controller / action with the language setting to IT or EN
thanks and sorry for may bad english
You will have to setup the your route with the translator adapter
@Lorenzo Massacci
I would like to know this also.
How can I translate the controller and action names in the url?
I use a Zend_Translate with gettext adapter.
J’ai à très peu de chose près la même méthode, à ça près que… ça ne marche pas
.
Plus précisément, ça marche pour toutes mes routes sauf default.
Exemple pour default : « …/fr » ou « …/fr/ » foirent (Uncaught exception ‘Zend_Controller_Router_Exception’ with message ‘No route matched the request’ thrown in …/Zend/Controller/Router/Rewrite.php on line 408) alors que « …/fr/index » ou « …/fr/default » fonctionnent. Et donc pour mes autres routes, ça fonctionne (vu que quelque chose suit la langue). « …/fr/admin/i18n/locales/list », par exemple, fonctionne très bien.
Si tu veux bien me donner ton avis, voici le code concerné.
Ma config en INI : http://paste2.org/p/669311
Mon plugin I18nRouter : http://paste2.org/p/669313
Merci !
Bon… comme toujours, quand je pose la question, je trouve la réponse 5 minutes après
…
Il suffisait de rajouter en ligne 19 :
$router->addRoute( ‘default-i18n’, $hook );
Je n’y pensais plus parce qu’avant tout se faisait automatiquement sur base de la config, et je voulais retirer ça de la config pour « nettoyer ».
Bref, affaire classée ! (on peut dire que ce problème n’était pas trop « dé-routant » — c’était mauvais… facile ET mauvais
)
[...] german is meaningless).. Hence, my first worry is to set the correct locale and translator.. In this tutorial the authour uses an easier approach: he has only two valid languages and needs to make just a few [...]
[...] the ZF train again! I asked the big G for a couple of best practices regarding this topic. I found this quite cool description which was working quite fast. But if you are a little bit advanced you know that this is not enough [...]
this doesn’t work poperly because the chain router has a bug:
http://framework.zend.com/issues/browse/ZF-8812