Yii2 Multilingual Website Url Rules

Hi,

I have a multilingual website on yii2 but I’m not able to set the right url rules to get it work fine with url patterns like this

http://example.com/[lang_code]/

I tried these rules but it didn’t work:




                '<language:\w+>/'=>'/site/index',

                '<language:\w+>/<controller>' => '<controller>',

                '<language:\w+>/<controller>/<action>' => '<controller>/<action>',

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

                '<language:\w+>/<controller>/<action>/<id:\d+>/<title>' => '<controller>/<action>',

                '<language:\w+>/<controller>/<id:\d+>/<title>' => '<controller>/index',

do you have to extend the request component? or i can achieve it with the url rules only?

Regards,

I followed those instructions (for yii 1.1) by migrating the code to yii 2.0. I have the same problem. The language is set in a session variable, so when I browse the site, the language stay the same. So far so good. But no language string is put in the URL like you mentioned.

Have you found a solution to this ?

OK, I fixed the problem. So the answer to your question is : yes you need to do something more than just put those URL rules. You need to extend the UrlManager. Here’s my code :




namespace app\components;

use yii\web\UrlManager;

use Yii;


class ZUrlManager extends UrlManager

{

    public function createUrl($params)

    {

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

            if (Yii::$app->session->has('language'))

                Yii::$app->language = Yii::$app->session->get('language');

            else if(isset(Yii::$app->request->cookies['language']))

                Yii::$app->language = Yii::$app->request->cookies['language']->value;

            $params['language']=Yii::$app->language;

        }

        return parent::createUrl($params);

    }

}



In the config file, here’s the settings for the urlManager component :




'urlManager' => [

            'class' => 'app\components\ZUrlManager',

            'enablePrettyUrl' => true,

            'showScriptName' => false,

            'rules' => [

                '<language:\w+>/<controller>/<action>/<id:\d+>/<title>' => '<controller>/<action>',

                '<language:\w+>/<controller>/<id:\d+>/<title>' => '<controller>/index',

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

                '<language:\w+>/<controller>/<action>' => '<controller>/<action>',

                '<language:\w+>/<controller>' => '<controller>',

                '<language:\w+>/'=>'site/index',

            ],



And for the sake of others, here’s my base controller class that all my other controllers extend (instead of extending directly the default controller class of the framework):




namespace app\components;

use Yii;


class Controller extends \yii\web\Controller

{

    public function init()

     {

        parent::init();

        // If there is a post-request, redirect the application to the provided url of the selected language

         if (isset($_POST['language'])) {

            $lang = $_POST['language'];

            $MultilangReturnUrl = $_POST[$lang];

            $this->redirect($MultilangReturnUrl);

        }

        // Set the application language if provided by GET, session or cookie

        if (isset($_GET['language'])) {

            Yii::$app->language = $_GET['language'];

            Yii::$app->session->set('language', $_GET['language']);

            $cookie = new \yii\web\Cookie([

                'name' => 'language',

                'value' => $_GET['language'],

            ]);

            $cookie->expire = time() + (60 * 60 * 24 * 365); // (1 year)

            Yii::$app->response->cookies->add($cookie);

        } else if (Yii::$app->session->has('language'))

            Yii::$app->language = Yii::$app->session->get('language');

        else if (isset(Yii::$app->request->cookies['language']))

            Yii::$app->language = Yii::$app->request->cookies['language']->value;


    }


     public function createMultilanguageReturnUrl($lang = 'fr_CA', $params = [])

    {

        if (count($_GET) > 0) {

            $arr = $_GET;

            $arr['language'] = $lang;

        } else

            $arr = array('language' => $lang);


        $param_temp = [

            $this->module->requestedRoute,

            'language' => $arr['language'],

        ];

        $params = array_merge($param_temp,$params);

        $urlManager = Yii::$app->urlManager;

        return $urlManager->createUrl($params);

    }

}



Hope it will help someone that is struggling as I did on converting those instructions to yii 2.0.

I didn’t succeed yet converting to yii 2.0 the widget for selecting the language.

I tried the above in yii2 it gives internal server error. I see that the widget fails somewhere. Can you also post how to create this widget in YII2

What I am missing below is the way to generate url in yii2. It fails on the following code

[code]

class UrlManager extends \yii\web\UrlManager

{

public function createmultiUrl($params)

{


    if (&#33;isset(&#036;params['language'])) {


        if (Yii::&#036;app-&gt;session-&gt;has('language'))


            Yii::&#036;app-&gt;language = Yii::&#036;app-&gt;session-&gt;get('language');


        else if(isset(Yii::&#036;app-&gt;request-&gt;cookies['language']))


            Yii::&#036;app-&gt;language = Yii::&#036;app-&gt;request-&gt;cookies['language']-&gt;value;


        &#036;params['language']=Yii::&#036;app-&gt;language;


    }


    return parent::createUrl(&#036;params);


}

}

[code]

Yes I could help. I edited the code I posted earlier. The rules for the urlManager where not in the good order. Also, the code for the function createMultilanguageReturnUrl has been changed a bit.

The code you posted is the same as mine for the function createmultiUrl.

The code for the widget is different than the one for Yii 1.1. Here’s mine :




class LanguageSelector extends \yii\base\Widget

{

    public $callingcontroller;


    public function run($params = [] )

    {

        $currentLang = Yii::$app->language;

        $languages = Yii::$app->params['languages'];

        return $this->render('languageSelector', [

            'currentLang' => $currentLang,

            'languages'=>$languages

        ]);

    }

}



and the view of the widget :




<div id="language-select">

<?php

    if(sizeof($languages) < 4) {

        // Render options as links

        $lastElement = end($languages);

        foreach($languages as $key=>$lang) {

            $controller = $this->context->callingcontroller;

            if($key != $currentLang) {

                $url = $controller->createMultilanguageReturnUrl($key, $controller->actionParams);

                echo yii\helpers\Html::a(

                    $lang,

                    $url

                );

            }

            else{

                echo '<b>' . $lang . '</b>';

            }

            if($lang != $lastElement){

                echo ' | ';

            }

        }

    }

    else {

        // Render options as dropDownList

        echo yii\helpers\Html::form();

        foreach($languages as $key=>$lang) {

            echo yii\helpers\Html::hiddenInput(

                $key,

                $this->getOwner()->createMultilanguageReturnUrl($key));

        }

        echo yii\helpers\Html::dropDownList('language', $currentLang, $languages,

            array(

                'submit'=>'',

            )

        );

        echo yii\helpers\Html::endForm();

    }

?>

</div>



I’m calling the widget in this way :




echo LanguageSelector::widget(['callingcontroller'=>$this->context]);



This extension will do the trick: https://github.com/codemix/yii2-localeurls

@ mfecteau, Can you please provide example code with the very detailed explanation with steps for integrate it. I’m searching the solution almost a week itself not get any proper solution for language selector.