Multiple languages in a CakePHP 2.* application in 5 steps

Written on 1 August 2012, 10:21pm

Tagged with: , ,

Below is a solution that I implemented in a CakePHP project needing internationalization (i18n).
It involves showing the language in the URL (so the URLs will look like app.com/:lang/:controller/:action/...) and storing it in the Session + Cookies.
It is basically the implementation described on http://nuts-and-bolts-of-cakephp.com. I only added some minor changes to make it work under CakePHP 2.* (the solution in the link above was implemented in November 2008, for CakePHP 1.3).
The implementation below was tested on CakePHP 2.2 (1 August 2012).
Feel free to add your comments/questions in the form below.

Comments inline:


// Step 1: app/Config/routes.php
Router::connect('/:language/:controller/:action/*',
                       array(),
                       array('language' => '[a-z]{3}'));

//Step 2: app/Config/core.php
Configure::write('Config.language', 'eng');

//Step 3: create app/View/Helper/MyHtmlHelper.php
App::uses('HtmlHelper', 'View/Helper');
class MyHtmlHelper extends HtmlHelper {
	public function url($url = null, $full = false) {
        if(!isset($url['language']) && isset($this->params['language'])) {
          $url['language'] = $this->params['language'];
        }
        return parent::url($url, $full);
   }
}

//Step 4: app/Controller/AppController.php
class AppController extends Controller {
	public $components = array('Cookie','Session');
	//set an alias for the newly created helper: Html<->MyHtml
	public $helpers = array('Html' => array('className' => 'MyHtml'));

	public function beforeFilter() {
          $this->_setLanguage();
        }

	private function _setLanguage() {
	//if the cookie was previously set, and Config.language has not been set
	//write the Config.language with the value from the Cookie
	    if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
	        $this->Session->write('Config.language', $this->Cookie->read('lang'));
	    } 
	    //if the user clicked the language URL 
	    else if ( 	isset($this->params['language']) && 
		($this->params['language'] !=  $this->Session->read('Config.language'))
	    		) {
	    	//then update the value in Session and the one in Cookie
	        $this->Session->write('Config.language', $this->params['language']);
	        $this->Cookie->write('lang', $this->params['language'], false, '20 days');
	    }
	}

	//override redirect
	public function redirect( $url, $status = NULL, $exit = true ) {
		if (!isset($url['language']) && $this->Session->check('Config.language')) {
			$url['language'] = $this->Session->read('Config.language');
		}
		parent::redirect($url,$status,$exit);
	}
}

//add the links to the languages:
//Step 5: app/View/...
echo $this->Html->link('English', array('language'=>'eng')); 
echo $this->Html->link('Français', array('language'=>'fre')); 

Update August 3rd 2012: Added ‘private’ visibility for the _setLanguage function
Update September 28th 2012: Modified the first step (app/Config/routes.php), adding more restrictive rules for the languages. Before, if the user somehow loaded an URL like /css/foo/bar – then ‘css’ was incorrectly considered a language.


	Router::connect('/:language/:controller/:action/*',
                       array(),
                       array('language' => 'eng|fre'));

	Router::connect('/:language/:controller',
                       array('action' => 'index'),
                       array('language' => 'eng|fre'));	

	Router::connect('/:language',
                       array('controller' => 'welcome', 'action' => 'index'),
                       array('language' => 'eng|fre'));

During my first half of the summer holidays, I took the opportunity to browse a few books in addition to reading my reader (which I am doing more or less daily). Doing this, I found a few things that influenced me and that I want to share.

1. Better than yesterday

The secret is to focus on making whatever it is you’re trying to improve
better today than it was yesterday. That’s it. It’s easy. And it’s possible
to be enthusiastic about taking real, tangible steps toward a distant goal.
book excerpt, PDF, 153KB

Where: The Passionate Programmer (2nd edition): Creating a Remarkable Career in Software Development by Chad Fowler.
Why: Because even if I have this principle embedded in my mind (see the first post of this blog: moving on to better things) and even if I used it successfully on multiple occasions – it’s always a good idea to highlight it.

2. Side projects

First, we love to complain about the type of work we get.
Whether assigned to us by a boss or work that we do for clients, we never
get to work on the cool stuff, the stuff that would inspire or excite us.
Second, we are full of bright ideas for the sites we work
on but are so often blocked by others on the project. We moan that they
don’t get it, that they don’t understand just how cool our ideas are.
I believe that side projects we do in our personal time
can be the answer to both of these issues.

Where: Side projects can cure our woes by Paul Boag.
Why: Because I agree with the importance of the side projects. In my free time, I am always working on at least one side project. Last example: the Ikea store locator

3. A long string of happy customers

The best thing for your career is a long string of happy customers
eager to recommend you because you did the right thing
by them and for the project. This goodwill will serve you orders
of magnitude better than the latest shiny object in the latest shiny
language or the latest shiny paradigm. While it is important, even
critical, to stay abreast of the latest trends and technologies this
should never happen at the cost of the customer.
-Chapter 1: Don’t Put Your Resume Ahead of the Requirements

Where: O’Reily’s 97 Things Every Software Architect Should Know – Collective Wisdom from the Experts by Richard Monson-Haefel
Why: Because I also see the importance of the happy customers.

4. Programmers have a lot on their minds

Programming languages, programming techniques, development
environments, coding style, tools, development process, deadlines,
meetings, software architecture, design patterns, team dynamics,
code, requirements, bugs, code quality. And more. A lot.

There is an art, craft, and science to programming that extends far
beyond the program. The act of programming marries the discrete world
of computers with the fluid world of human affairs. Programmers mediate
between the negotiated and uncertain truths of business and the crisp,
uncompromising domain of bits and bytes and higher constructed types.

Where: O’Reily’s 97 Things Every Programmer Should Know – Collective Wisdom from the Experts by Kevlin Henney (public wiki)
Why: Because the man is right 🙂 The programmers have indeed a lot on their minds…

Ronnie O’Sullivan

Written on 7 May 2012, 09:51pm

Tagged with: ,

Snooker World Champion 2012

“Ronnie O’Sullivan can win as many world titles as he wants to, he’s got more talent than any human being deserves to have, he’s been sprinkled with star dust.”
-John Parrott

“The balance in his game is magnificent and when he plays like that he truly is the greatest player ever to play the game. He’s a demi-god with what he can do with a cue in his hand.”
-Steve Davis