Yii2 framework學習筆記(三) -- 語言與國際化

國際化功能一般很少用到,但作爲學習,還是有必要接觸一下。


國際化最常用到的方法是\Yii::t,官方文檔如下

t() public static method

Translates a message to the specified language.

This is a shortcut method of yii\i18n\I18N::translate().

The translation will be conducted according to the message category and the target language will be used.

You can add parameters to a translation message that will be substituted with the corresponding value after translation. The format for this is to use curly brackets around the parameter name as you can see in the following example:

$username = 'Alexander';
echo \Yii::t('app', 'Hello, {username}!', ['username' => $username]);

Further formatting of message parameters is supported using the PHP intl extensions message formatter. See yii\i18n\I18N::translate() for more details.

public static string t ( $category, $message, $params = [], $language null )
$category string

The message category.

$message string

The message to be translated.

$params array

The parameters that will be used to replace the corresponding placeholders in the message.

$language string

The language code (e.g. en-USen). If this is null, the current application language will be used.

return string

The translated message.


參數有4個,但常用到的是前兩個。

第一個是組別,組別的定義放在config/main-local.php下。

Yii2默認用的是英語(en-US),現在添加中文支持(zh-CN)

在component下添加如下塊

    'components' => [
        ...
    	'i18n' => [
    		'translations' => [
    			'common' => [
    				'class' => 'yii\i18n\PhpMessageSource',
    				'basePath' => '@common/messages',
    				'fileMap' => [
    					'common' => 'common.php',
    				],
    			],
    		],	
    	],
        ...
    ],

這段代碼定義了一個名爲common的組別,解析翻譯文件用的是默認的類yii\i18n\PhpMessageSource,翻譯文件放置在common/messages下,翻譯文件是common.php。

根據配置,建立如下的目錄結構


翻譯文件以數組的方式組織的,內容如下

<?php
return [
	'Signup' => '註冊',
	'Login' => '登陸',
	'Logout' => '登出',
	'Home' => '首頁',
	'Contact' => '反饋',
	'About' => '關於',
];


然後我們在layouts文件裏做翻譯,在/views/layouts/main.php裏修改如下:

    $menuItems = [
        //['label' => 'Home', 'url' => ['/site/index']],
        //['label' => 'About', 'url' => ['/site/about']],
        //['label' => 'Contact', 'url' => ['/site/contact']],
        ['label' => \Yii::t('common', 'Home'), 'url' => ['/site/index']],
        ['label' => \Yii::t('common', 'About'), 'url' => ['/site/about']],
        ['label' => \Yii::t('common', 'Contact'), 'url' => ['/site/contact']],
    ];

打開頁面,看看是否生效。


遺憾的是,並不能生效。。。。。


究其原因,是因爲網站的根語言還是en-US,需要配置爲zh-CN。

在common/config/main-local.php裏,添加如下配置:

<?php
return [
   'language' => 'zh-CN',
   ...
];
再檢查一下是否生效。


可以看到翻譯已經生效。


但用Yii::t方法的主要原因是要實現多語言,如果只是顯示一種語言,還不如做hardcode(yii2框架實際做的也是hardcode的語言顯示)

yii2沒有提供現成的切換語言的控件,需要我們自己開發一個。

實現參考http://www.yiiframework.com/wiki/294/seo-conform-multilingual-urls-language-selector-widget-i18n/,並做了適度的簡化,不做seo方面的考慮。

實現的主要思路是把用戶選擇的語言保存到cookie中,每次用戶訪問頁面前,將語言設置爲cookie中的值。爲什麼需要每次設置語言,原因如下

Note: If we don't set Yii::app()->language explicitly for each request, it will be equal to its default value set in the confg file. If it is not set in the config file, it will be equal to the value Yii::app()->sourceLanguage, which defaults to 'en_us'. 

大概意思就是如果不每次進行設值的話,系統將自己採用默認語言,一般是英語。


1.準備素材,國旗兩面,放到frontend/web/image/下,命名爲en.png和zh.png。


2.在/common/config/main-local.php裏配置可用的語言,供我們在控件中調用

<?php
return [
    'language' => 'zh-CN',

    'components' => [
        ...
    ],
	'params' => [
		'availableLanguages' => [
			'zh-CN' => ['img' => 'image/zh.png', 'desc' => '中文'],
			'en-US' => ['img' => 'image/en.png', 'desc' => 'English'],
		],
	],
    ...
];

3.在/common/widgets/下新建一個php文件,命名爲LanguageSelector.php,內容如下:

<?php

namespace common\widgets;

use Yii;
use yii\helpers\Html;
use yii\helpers\Url;

class LanguageSelector
{
	public static function getMenu()
	{
		$lang = Yii::$app->language;
		$avLang = Yii::$app->params['availableLanguages'];
		$isMatch = false;
		foreach ($avLang as $key => $value) {
			if($key == $lang) {
				$tag = LanguageSelector::buildImgTag($value['img'], $value['desc']);
				$isMatch = true;
			}
		}
		if(!$isMatch) {
			$tag = LanguageSelector::buildImgTag($avLang[0]['img'], $avLang[0]['desc']);
		}
		$return = [
			'label' => $tag, 
			'items' => LanguageSelector::buildMenuItems($avLang),
		];
		
		return $return;
	}	
	
	private static function buildImgTag($src, $desc)
	{
		return '<img src="' . $src . '" alt="' . $desc . '">';
	}
	
	private static function buildMenuItems($langs)
	{
		foreach ($langs as $key => $value) {
			$link = Html::a(LanguageSelector::buildImgTag($value['img'], $value['desc']) . ' ' . $value['desc'], Url::home(), [
					'title' => LanguageSelector::buildImgTag($value['img'], $value['desc']) . ' ' . $value['desc'],
					'onclick'=>"
					     $.ajax({
					    type     :'POST',
					    cache    : false,
					    url  : '" . Url::toRoute("ajax/lang") . "',
						data: { _lang : '" . $key . "' },
					    success  : function(response) {
					        window.location.reload();
					    }
					    });return false;",
			]);
			$menuItems[] = '<li>' . $link . '</li>';
		}
		return $menuItems;
	}
}

主要做的事情爲:

  • 讀取main-local.php中的配置項,形成數組。
  • 渲染菜單。
  • 爲菜單中的按鈕綁定事件,當點擊時觸發ajax請求,ajax順利返回後刷新頁面。
4.添加處理ajax的controller。在frontend/controllers下新建AjaxController.php,添加如下代碼:
<?php

namespace frontend\controllers;

use Yii;
use yii\web\Controller;
use common\components\SelectLanguageBehavior;
use yii\web\cookie;

class AjaxController extends Controller {
	public $layout = false;
	
	public function actionLang() {
		if (isset($_POST['_lang']))
		{
			$lang = SelectLanguageBehavior::getSelectedLanguage($_POST['_lang']);
			Yii::$app->language = $lang;
			$cookie = new cookie([
					'name' => '_lang',
					'value' => $lang,
			] );
			$cookie->expire = time() + (60*60*24*365); // (1 year)
			Yii::$app->response->cookies->add($cookie);
		}
		return "success";
	}
	
}

其中重要的是把$layouts設爲false,防止ajax返回渲染多餘的東西。

5.增加一個動作(Behaviors),用來每次用戶訪問頁面時修改語言。
在common/components下(如果沒有該目錄則新建目錄),新建SelectLanguageBehavior.php,內容如下
<?php
namespace common\components;

use yii\base\Application;
use yii\base\Behavior;
use yii\web\cookie;
use Yii;
class SelectLanguageBehavior extends Behavior
{
	public function events()
	{
		return [
				Application::EVENT_BEFORE_REQUEST => 'beforeRequest',
		];
	}
	
	public function beforeRequest($event) {
		$app = Yii::$app;
	
		$lang = SelectLanguageBehavior::getSelectedLanguage(Yii::$app->request->cookies->getValue('_lang'));
		$app->language = $lang;
	}
	
	public static function getSelectedLanguage($val) {
		$langs = Yii::$app->params['availableLanguages'];
		foreach ($langs as $key=>$value) {
			if($val == $key) {
				return $val;
			}
		}
		return key($langs);
	}
}

6.將該動作綁定到系統中。
在common/config/main-local.php中添加as beginRequest項
<?php
return [
	'language' => 'zh-CN',

    'components' => [
        ...
    ],
    ...
	'as beginRequest' => [
			'class' => 'common\components\SelectLanguageBehavior',
	],
];

7.將該控件添加到頁面上。
在frontend/views/layouts/main.php裏,添加代碼顯示我們的控件,因爲控件中帶html代碼,還要防止它做轉義處理
    ...
    if (Yii::$app->user->isGuest) {
        $menuItems[] = ['label' => Yii::t('common', 'Signup'), 'url' => ['/site/signup']];
        $menuItems[] = ['label' => Yii::t('common', 'Login'), 'url' => ['/site/login']];
    } else {
        $menuItems[] = [
            'label' => Yii::t('common', 'Logout') . ' (' . Yii::$app->user->identity->username . ')',
            'url' => ['/site/logout'],
            'linkOptions' => ['data-method' => 'post']
        ];
    }
	
	// add this line
        $menuItems[] = \common\widgets\LanguageSelector::getMenu();
	
	echo Nav::widget([
        'options' => [
        	'class' => 'navbar-nav navbar-right',
        	],
        'items' => $menuItems,
        // add this line
    	'encodeLabels' => false,
    ]);
	...

8.打開頁面查看效果


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章