» » » Language switcher in Yii2

Language switcher in Yii2

posted in: Yii2.0 framework

Yii version 2.0.13.1

Currently, I am building the custom application with Yii2. I want to add the language switcher in the application. I found some posts that help but these posts won’t explain well. So I try to explain what I did here.

 

Here what we will do:

 

Create the static value in config/params.php

We add the static value for locale and calendar that we will set in Yii::$app->formatter. We add the static value in config/params.php.

    'formattedLanguages' => [
        'en-US' => [
            'locale' => 'en_US',
            'calendar' => '',
        ],
        'th-TH' => [
            'locale' => 'th_TH@calendar=buddhist',
            'calendar' => \IntlDateFormatter::TRADITIONAL,
        ],
    ],

 

Create a language dropdown list in layout/main.php
    <?= Html::beginForm(['site/language'], 'post', [
                'enctype' => 'multipart/form-data',
                'id' => 'lang-form',
     ]) ?>
    <?= Html::dropDownList('language', Yii::$app->language, ['en-US' => 'English', 'th-TH' => 'Thai']) ?>
    <?= Html::submitButton('Change') ?>
    <?= Html::endForm() ?>

 

Create a actionLanguage() in the controller

We set the application language and set the cookie for storing the selected language, locale and calendar. We will use the cookie in the LanguageSelector component which we will talk about it later.

    $language = Yii::$app->request->post('language');
    Yii::$app->language = $language;

    $languageCookie = new Cookie([
        'name' => 'language',
        'value' => $language,
        'expire' => time() + 60 * 60 * 24 * 30, // 30 days
    ]);
    Yii::$app->response->cookies->add($languageCookie);

    $localeCookie = new yii\web\Cookie([
        'name' => 'locale',
        'value' => Yii::$app->params['formattedLanguages'][$language]['locale'],
        'expire' => time() + 60 * 60 * 24 * 30, // 30 days
    ]);
    Yii::$app->response->cookies->add($localeCookie);

    $calendarCookie = new yii\web\Cookie([
        'name' => 'calendar',
        'value' => Yii::$app->params['formattedLanguages'][$language]['calendar'],
        'expire' => time() + 60 * 60 * 24 * 30, // 30 days
    ]);
    Yii::$app->response->cookies->add($calendarCookie);

 

Create a LanguageSelector component

Next, we create a LanguageSelector component in components/LanguageSelector.php. The component will get the language setting from the cookie and assign to the application language, locale and calendar formatter. The component will be loaded before the layouts and views.

Important note:

  • PHP intl extension must be enabled.
  • Calendar value must be integer.
    namespace frontend\components;
    use yii\base\BootstrapInterface;

    // https://github.com/samdark/yii2-cookbook/blob/master/book/i18n-selecting-application-language.md#support-selecting-language-manually
    class LanguageSelector implements BootstrapInterface
    {
        public $supportedLanguages = [];

        /**
        * 
        * It is a good idea to set the language selector in BootstrapInterface class.
        * Then sets this component in config/main.php and set this component in bootstrap property.
        * 
        * Because this bootstrap class will be loaded at very first.
        * You can check the "Log" in Yii debug tool to see this component is loaded first.
        * 
        */
        public function bootstrap($app)
        {
            $preferredLanguage = isset($app->request->cookies['language']) ? (string)$app->request->cookies['language'] : null;
            $preferredLocale = isset($app->request->cookies['locale']) ? (string)$app->request->cookies['locale'] : null;
            $preferredCalendar = isset($app->request->cookies['calendar']) ? (string)$app->request->cookies['calendar'] : null;
            // or in case of database:
            // $preferredLanguage = $app->user->language;

            if (empty($preferredLanguage)) {
                $preferredLanguage = $app->request->getPreferredLanguage($this->supportedLanguages);
            }
            $app->language = $preferredLanguage;


            // Set Locale ID and Calendar for Buddhist calendar
            // Important: 
            // If the PHP intl extension is not available, setting this calendar property will have no effect.
            // This setting will chagne from คศ to พศ     
            // 
            // @link 
            // http://www.yiiframework.com/doc-2.0/yii-i18n-formatter.html#$locale-detail
            // http://www.yiiframework.com/doc-2.0/yii-i18n-formatter.html#$calendar-detail  
            $app->formatter->locale = $preferredLocale;
            $app->formatter->calendar = (int)$preferredCalendar;   // calendar must be integer. Cookie always stores as string. So you must convert the cookie value to integer.  
        }
    }

In order to use this component, you set in config/main.php. We set in bootstrap property.

    return [
        'bootstrap' => [
            [
                'class' => 'app\components\LanguageSelector',
                'supportedLanguages' => ['en-US', 'th-TH'],
            ],
        ],
        // ...
    ];

 

Create a JS file for calling the actionLanguage() via ajax

Finally, we add the js file in order to call the actionLanguage() via ajax and reloads the page. You can add as the inline js or add to the assets bundle.

    // Reload the current page after switch languages
    $("form#lang-form").submit(function () {
        var form = $(this);
        // submit form
        $.ajax({
            url: form.attr("action"),
            type: "post",
            data: form.serialize(),
            success: function (response) {
                // reload the page after selecting a language
                location.reload();
            },
            error: function () {
                console.log("Ajax: internal server error");
            }
        });
        return false;
    });

 

Display the date and date time

Because we set the Yii::$app->formatter when we want to display the date or date time in views, grid view and detail view, we must use the Yii::$app->formatter.

Yii::$app->formatter->asDate('myDate');

or you can use the shortcut format in grid view and detail view.

created_at:date

You will see the result below.

English => 10 dec 2017

Thai => 10 ธค 2560