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
- create a language dropdown list in layout/main.php
- create a actionLanguage() in the controller
- create a LanguageSelector component
- create a JS file for calling the actionLanguage() via ajax
- display the date and date time
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 it 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 an 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 the 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 the grid view and detail view.
created_at:date
You will see the result below.
English => 10 dec 2017
Thai => 10 ธค 2560