Implementing i18n

I am trying to implement i18n in my application…

The code i have so far gets the job done but i would like if someone could suggest a better and more effecient way to go about it if possible.

This is what i have done:

i created a base controller in components which all other controllers extend, this is the source




<?php


class BaseController extends CController

{	

	public $app;

	.............


	public function init()

	{

		$this->app = Yii::app();

		

		//$this->_setTheme();

		$this->_setLanguage();

	}

	..........

	

	private function _setLanguage()

	{

		if(isset($_GET[$this->app->params['varLanguage']]))

		{

			$language = $_GET[$this->app->params['varLanguage']];

		}else if(isset($_COOKIE[$this->app->params['varLanguage']]))

		{

			$language = $_COOKIE[$this->app->params['varLanguage']];

		}else{

			$language = $this->app->params['defaultLanguage'];

		}

		if(!array_key_exists($language,$this->app->params['languages']))

		{

			$language = $this->app->params['defaultLanguage'];

		}

		if(!isset($_COOKIE[$this->app->params['varLanguage']])||$_COOKIE[$this->app->params['varLanguage']]!=$language)

		{

			setcookie($this->app->params['varLanguage'],$language,$this->app->params['cookieExpire']);

		}

		$this->app->setLanguage($language);

	}

	..........

}

and i have this in my config file




	'params'=>array(

		........

		'cookieExpire'=>time()+3600,

		........

		'defaultLanguage'=>'en_us',

		'varLanguage'=>'language',

		'languages'=>array(

			'en_us'=>array(

				'name'=>'English (US)',

				'encoding'=>'utf-8',

			),

			/*'zh_cn'=>array()*/

		),

	),



Setting a language looking more or less optimized. I would recommend using a wrapper class for managing cookies:


<?php

/**

* Manage Cookies

*/

class MCookie

{

    /**

    * Get a cookie value

    * @param string $name

    * @return string

    */

    public static function get($name)

    {

        $cookies=Yii::app()->request->getCookies();

        return is_object($cookies[$name]) ? $cookies[$name]->value : null;

    }


    /**

    * Whether has a cookie

    * @param string $name

    * @return bool

    */

    public static function has($name)

    {

        $cookies=Yii::app()->request->getCookies();

        return is_object($cookies[$name]);

    }


    /**

    * Set a cookie value

    * @param string $name

    * @param string $value

    * @param array $params

    */

    public static function set($name,$value,$params=array())

    {

        $cookie=new CHttpCookie($name,$value);

        $cookie->expire=time() + 3600*24*30; // by default to 30 days from now

        if(isset($params['expire']))

        {

            if(is_numeric($params['expire']))

            {

                $cookie->expire=(int)$params['expire'];

                // don't forget, expire is a timestamp

                $cookie->expire<time() && ($cookie->expire += time());

            }

            else

                {/*write log*/}

        }

        if(isset($params['domain']))

        {

            if(is_string($params['domain']) || is_numeric($params['domain']))

                $cookie->domain=(string)$params['domain'];

            else

                {/*write log*/}

        }

        if(isset($params['path']))

        {

            if(is_string($params['path']) || is_numeric($params['path']))

                $cookie->path=(string)$params['path'];

            else

                {/*write log*/}

        }

        if(isset($params['secure']))

        {

            if(is_bool($params['secure']))

                $cookie->secure=$params['secure'];

            else

                {/*write log*/}

        }

        if(isset($params['httpOnly']))

        {

            if(is_bool($params['httpOnly']))

                $cookie->httpOnly=$params['httpOnly'];

            else

                {/*write log*/}

        }

        $cookies=Yii::app()->request->getCookies();

        $cookies[$name]=$cookie;

    }


    /**

    * Unset a cookie

    * @param string $name

    */

    public static function unsetIt($name)

    {

        $cookies=Yii::app()->request->getCookies();

        unset($cookies[$name]);

    }

}

then instead of


if(isset($_COOKIE[$this->app->params['varLanguage']]))

use


if(MCookie::has($this->app->params['varLanguage']))

and so on…

Using a similar function, but as a component. Not really sure why you do $this->app = Yii::app();, and perhaps use CHttpCookie. I also look at Yii::app()->request->preferredLanguage, so see if I can offer that language right away.

To go a bit further:

My LangHandler component adds a 2-letter parameter before the path. But for SEO reasons, it would be a lot nicer to have translated paths in the URL. This would require much more than that, and can (will) make things complicated.

Currently I do this for some urls by defining routes, but that’s less than perfect… Still I can’t get it out of my head ;). Anyone already done something like that?

PS: if the requested language could be determined before routes something like this could work:


Yii::t('route', 'controller').'/_a' => 'controller/_a',