Articles récents
Commentaires récents
- In i18n routes with CakePHP 1.3
- pierre_martin wrote: Hi everyone and thank you for the feedbacks! Since this article was published, we improved...
- In i18n routes with CakePHP 1.3
- Mateusz Mucha wrote: Thank you!
- In i18n routes with CakePHP 1.3
- Piotr wrote: Wow! That's great and usefull. Ways easier than with old methods. I added some code to update...
- In i18n routes with CakePHP 1.3
- Lee wrote: Once you set $url['lang'] when empty is doesn't update $this-params with the default...
- In CakePHP Migrations plugin: easily version and deploy whole applications
- Remigijus wrote: When I am trying to run 'migration generate' for first time, my migration file 'up' has value...
Catégories
Il n'y a aucune catégorie à afficher
i18n routes with CakePHP 1.3
Ecrit le Thu, Aug 5th 2010, 10:00 dans Uncategorized
Internationalizing a CakePHP application can be tricky when it comes to deal with i18n urls. We will see in this article how the Custom route classes introduced by CakePHP 1.3 could be used to add the current language to your urls in a few lines of code.
EDIT: This proof of concept has now been improved and a better version of the code below can be found in CakeDC's I18n plugin on Github
Requirements
This article will not go too deep in internationalizing an application as many resources already exist about it. We suppose the following:
- Your application defines the current language on given the language code passed in the url
- The available languages are configured via Configure::write('Config.languages', array('eng', 'fre', 'deu'));
- You use the CakePHP array syntax for defining urls:
- $this->Html->link('link', array('controller' => 'posts', 'action' => 'view', $post['Post']['id']));
- $this->redirect(array('controller' => 'posts', 'action' => 'index'));
- Router::url(array('controller' => 'posts', 'action' => 'index'), true);
Custom routes were already introduced by Mark Story on his blog, so we will not do it again here... before continuing be sure you have read "Using custom Route classes in CakePHP"
Show me some code!
I18nRoute
As I said (or not), routes are probably the best place for customizing your urls and add information in them... much more better at least than overriding the Helper::url() method in an AppHelper class!
Custom routes introduced a way to customize how routes are processed in a very easy and powerful way (i.e ~20 lines of code). It is a bit like wrapping the Router class in CakePHP 1.2, a good example of this was the CroogoRouter.
First, we are going to create an I18nRoute class extending CakeRoute in the "/libs/routes/i18n_route.php" file. Here is its code:
<?php
class I18nRoute extends CakeRoute {
/**
* Constructor for a Route
* Add a regex condition on the lang param to be sure it matches the available langs
*
* @param string $template Template string with parameter placeholders
* @param array $defaults Array of defaults for the route.
* @param string $params Array of parameters and additional options for the Route
* @return void
* @access public
*/
public function __construct($template, $defaults = array(), $options = array()) {
$options = array_merge((array)$options, array(
'lang' => join('|', Configure::read('Config.languages'))
));
parent::__construct($template, $defaults, $options);
}
/**
* Attempt to match a url array. If the url matches the route parameters + settings, then
* return a generated string url. If the url doesn't match the route parameters false will be returned.
* This method handles the reverse routing or conversion of url arrays into string urls.
*
* @param array $url An array of parameters to check matching with.
* @return mixed Either a string url for the parameters if they match or false.
* @access public
*/
public function match($url) {
if (empty($url['lang'])) {
$url['lang'] = Configure::read('Config.language');
}
return parent::match($url);
}
}
The most important part of the code is in the "match()" method. We just add the current language to the url "lang" named param if it was not set. The constructor was also overriden to add a regex pattern for the "lang" param. Thus, only lang prefixes defined in your list of available languages will be parsed by the route.
Define your routes
It is now time to use this custom route in your application. Here is how the default route for pages could be defined in "/config/routes.php":
App::import('Lib', 'routes/I18nRoute');
Router::connect('/:lang/pages/*', array('controller' => 'pages', 'action' => 'display'), array('routeClass' => 'I18nRoute'));
- import the library file containing the custom route
- add a ":lang" param in where you want the language code appear in the url
- tell the Router you want to use this custom class (third param)
Link from everywhere!
Now you won't have to worry about the language code transmitted in your urls... every generated link will contain the current language code. If you want to switch the language (for instance switching to the French version of your application), you will just have to add the "lang" param to the url array.
Here are some examples of urls which would be generated on the "/eng/posts/index" page:
$this->Html->link(__('French', true), array_merge($this->passedArgs, array('lang' => 'fre'))); // /fre/posts/index
$this->Html->link('link', array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); // /eng/posts/view/2
Disclaimer
This code is experimental and the article shows you how to use CustomRoutes to implement this basic feature. Many improvements could be added to fit your needs (no language code for the default application lang, short languages code...)
Even if the tests we made were successful, we have not used this code in production yet so there may be "real word" use cases that are not handled correctly with this solution... if you find one, please tell us in the comments!
Retour aux articles de Pierre's

Qu'est-ce que OpenID ?
OpenID est un nouveau standard ouvert qui permet de se connecter à des sites web grâce à une simple URL vous appartenant. Cette URL peut être votre page personnelle ou blog, ou peut vous être fournie par un site web que vous utilisez. Dans tous les cas, vous n'avez qu'à vous connecter une seule fois auprès de votre fournisseur OpenID, vous permettant ainsi de n'avoir qu'un seul mot de passe à maintenir.Learn more.
Comment est-ce que CakeDC utilise OpenID ?
Vous pouvez utiliser votre identité OpenID lorsque vous postez des commentaires sur le site. Lorsque vous voyez un champ de formulaire avec
il suffit de renseigner votre identité OpenID pour vous permettre de poster. Nous acceptons également les identités Google et Yahoo!. Utilisez simplement soit "google.com" soit "yahoo.com" et notre librairie OpenID ira chercher vos informations au bon endroit.
Commentaires:
Add New Comment
Redirect
Reply | Lee | posted on 13/8/10
-
Reply | Piotr | posted on 1/9/10
Just what I needed
Reply | Mateusz Mucha | posted on 9/9/10
Update
Reply | pierre_martin | posted on 17/9/10