Url Manger doesn't like prefixes?

I am trying to add the language code in front of the url.

I am using CUrlManager extension class, which adds the ‘/en/’ or whatnot to the route before running the createUrl method.

Everything was fine, UNTIL I noticed that the proper rules do not apply to the url now.

Now I am getting the parsed GET parameter names in the url.

For instance - mysite/en/controller/action/id/1

What I should have according to the rules - mysite/en/controller/action/1

When I remove the language code adding from the route - it works fine.

I’d consider this a pretty nasty bug.

Has someone worked his way around this?

You need a URL rule like the following:




'<lang:\w+>/<controller:\w+>/<action:\w+>' => '<controller>/<action>'



The language code can be read from $_GET[‘lang’] if this rule applies in a request.

That’s exactly what I’m doing… both ways DON’T WORK, and it remains like mysite/en/controller/action/id/1




'<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

'<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id>' => '<controller>/<action>',




silence… awesome…

Test with


'<lang:\w+>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>'

if it doesn’t work paste some more code from your CUrlManager extension and main.php configuration of the urlManager

Doesn’t work with that rule…

Ok, here’s the CUrlManager of mine:




class ELangCUrlManager extends CUrlManager

{	

    public function createUrl($route,$params=array(),$ampersand='&')

    {

        if (!isset($params['lang'])) {

            $lang = Yii::app()->GetLanguage();

        } else {

            $lang = $params['lang'];

            unset($params['lang']);

        }


        if ($lang == 'en_us') $lang = 'en';


        if (strpos($route, 'srbac') === false) {

            return parent::createUrl('/'.$lang.'/'.$route, $params);

        } else {

            return parent::createUrl($route, $params);

        }

    }

}



Additional class Lang Manager:




class ELangHandler extends CApplicationComponent {

    public $languages = array();

    

    public function init() {

      //  Yii::app()->sourceLanguage = 'en';

        $this->languages = array();


        $lang = Languages::model()->findAll();

        foreach($lang as $v) {

            $this->languages[] = $v->xla_name;

        }


        $this->parseLanguage();

    }


    private function parseLanguage() {

        Yii::app()->urlManager->parseUrl(Yii::app()->getRequest());

        if(!isset($_GET['lang'])) {

            $defaultLang = 'en';

            Yii::app()->setLanguage($defaultLang);


        }elseif($_GET['lang']!=Yii::app()->getLanguage() && in_array($_GET['lang'],$this->languages)) {

            Yii::app()->setLanguage($_GET['lang']);

        }

    }

}



And the complete set of URL Rules I have:




'urlManager'=>array(

            'class'=>'application.extensions.langhandler.ELangCUrlManager',

			'urlFormat'=>'path',

			'showScriptName' => false,

			'rules'=>array(


                '<lang:\w{2}>/gii'=>'gii',

        	    '<lang:\w{2}>/gii/<controller:\w+>'=>'gii/<controller>',

    	        '<lang:\w{2}>/gii/<controller:\w+>/<action:\w+>'=>'gii/<controller>/<action>',





                '<lang:\w{2}>/news/<action:\w+>/<id:\d+>/<title>/<page:\d+>' => 'news/<action>',  // news pagination

                '<lang:\w{2}>/news/<action:\w+>/<id>/<id2:\d+>/<page:\d+>' => 'news/<action>',




                '<lang:\w{2}>/faq/<action:\w+>/<cid:\d+>' => 'faq/<action>',

                '<lang:\w{2}>/faq/<action:\w+>/<cid:\d+>/<scid:\d+>' => 'faq/<action>',

                '<lang:\w{2}>/register/<action:\w+>/<id:\w+>/<code:\w+>' => 'register/<action>',


                '<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',

                '<lang:\w{2}>/<controller:\w+>/<action:\w+>/<provider:\w{32}>' => '<controller>/<action>',





                '<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id>' => '<controller>/<action>',

                '<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id>/<id2:\d+>' => '<controller>/<action>',

                '<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id>/<id2:\d+>/<title2>' => '<controller>/<action>',


                '<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id:\d+>/<title>' => '<controller>/<action>',

                '<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id:\d+>/<title>/<id2:\d+>/<title2>' => '<controller>/<action>',




				'<lang:\w{2}>/<controller:\w+>/<id:\d+>'=>'<controller>/view',

				'<lang:\w{2}>/<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

				'<lang:\w{2}>/<controller:\w+>/<action:\w+>'=>'<controller>/<action>',


			),

		),



Your custom urlManager is confusing me. I suggest you use the well tested extension for that purpose: http://www.yiiframework.com/extension/langurlmanager/ and than try again.

I am using it, I just slightly modified it to get language list from db.

Can you please explain why you delete the lang parameter (unset($params[‘lang’]); )?

Can you explain this: return parent::createUrl(’/’.$lang.’/’.$route, $params); => the first parameter is expected to be the route namely controller/action how do you fit in the lang param there?

Have you found a solution to this? I’m trying to achieve the exact same thing, currently writing a MultiLanguage component to handle languages from database and I’m about to start writing behavior for AR to support tables with record translations.

Currently the URL Management (your issue) is what I’m trying to do.

One approach might be to have routes with and without the lang param. One of them should match. You already check if the lang param "isset". The issue is that it seems like too much redundancy if there is a simple rule to make the <lang:> param optional.

Yeah, I actually effed up a bit, then I downloaded http://www.yiiframework.com/extension/langurlmanager/ this extension and it worked fine :)