Multilanguage web site controlling by get request and database allowed languages

You are viewing revision #9 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.

« previous (#8)

  1. You can control your languages in admin
  2. 1.init()
  3. 2.processUrl()
  4. 3.beforeAction()
  5. UrlMAnager
  6. Configure ROUTES
  7. Language routes

You can control your languages in admin

First, you have to have create database table for default language and allowed languages.

CREATE TABLE IF NOT EXISTS `tbl_languages` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `lang` varchar(2) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `flagpath` varchar(40) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `active` tinyint(1) NOT NULL,
  `main` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

INSERT INTO `tbl_languages` (`id`, `name`, `lang`, `flagpath`, `active`, `main`) VALUES
(1, 'English', 'en', '/img/lang/en.jpg', 1, 1),
(2, 'Croatian', 'hr', '/img/lang/hr.jpg', 1, 0);

After Table you have to make model for use:

class Lang extends CActiveRecord{
    
        /*
     * This method is used for static model calls
    */
    public static function model($className = __CLASS__) {
        return parent::model($className);
    }
    
    public function tableName() {
        return "tbl_languages";
    }
    
    /*
     * Function For check lang by get request eq /hr/site/index
     * If language is by get request found in database and active langage will return current link eg /hr/site/active if your request is eg /fr/site/index
     * in this case will return /en/site/index while fr langage is not in database
     * @param cod varchar 2
     * @param route current action route 
     * @param redirection default to true to redirect from eg /fr/ to /en/ while fr dont exists as language 
     */
    public static function findByCode($cod,$route,$redirect = true){
        $cod = substr($cod,0,2);
        $data = self::model()->find('lang=:LANG AND active = 1',array(':LANG'=>$cod));
        if(empty($data)){
            $lang = self::getdefaultLanguage();
          
            if($redirect == true){
                if(preg_match("/index/", $route))
                Yii::app()->controller->redirect(Yii::app()->homeUrl.$lang.'/');        
                else        
                Yii::app()->controller->redirect(Yii::app()->homeUrl.$lang.'/'.$route);
            }else
            return $lang;    
        } 
        else
        return $data->lang;
    }
    
    /*
     * get default language
     */
    public static function getdefaultLanguage(){
        return self::model()->find('main = 1')->lang;
    }
    
  
}   

Now we have to make some functions in component Controller which extends CController

1.init()

On every Controller instance set the language

2.processUrl()

Find the language and set current route

3.beforeAction()

Do that before each action.

class Controller extends CController{
        
        /*
         * On every Controller instance set language from get if is index page get main language
         */
        public function init(){
            if(isset($_GET['lang']))
                Yii::app()->setLanguage($_GET['lang']);
            else
                Yii::app()->setLanguage(Lang::getdefaultLanguage());
            parent::init();
        }

       /*
         * ProcesUrl method used for resolving languages if dont have get language
         * System gets default language defined from database
         */
        public static function processUrl(){

                if(isset($_GET['lang'])){
                    return Lang::findByCode(Yii::app()->language,  Yii::app()->controller->route);
                }else{ 
                    return Lang::findByCode(Lang::getdefaultLanguage(),  Yii::app()->controller->route);   
                }
        }
        
         /*
         * Aftereach action processUrl
         */
         protected function beforeAction($action) {
            self::processUrl();
            return parent::beforeAction($action);
        }


}

UrlMAnager

And final make the UrlMAnager class to component folder for rewrite current createUrl for each call add automatic lang to url

class UrlManager extends CUrlManager{
    
    /*
    * rewriten behavior
    */
    public function createUrl($route, $params = array(), $ampersand = '&') {
        //because if you wont to define language manually 
        if(empty($params['lang'])){
        $params['lang'] = Controller::processUrl();
        }
        return parent::createUrl($route, $params, $ampersand);
    }
    
    
}

Configure ROUTES

Add it to main.php

Language routes

1. rule is default
2. rule is for /hr/admin remove index from controller
3. rule is for each controller action /en/site/index
4. rule is for redirecting /en/ for redirecting index to language /de/ /fr/

depends on database

'urlManager'=>array(
'class'=>'UrlManager',    
'urlFormat'=>'path',
'rules'=>array(    
'/'=>'site/index',      
'<lang>/<controller:\w+>'=>'<controller>/index', 
'<lang>/<controller:\w+>/<action:\w+>'=>'<controller>/<action>',   
'<lang>'=>'/',          
),
'showScriptName'=>false,
);