首頁 > php教程 > PHP开发 > 主體

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

黄舟
發布: 2016-12-30 09:44:13
原創
1886 人瀏覽過

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

國際化最常用到的方法是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:
登入後複製
[code]$username = 'Alexander';
echo \Yii::t('app', 'Hello, {username}!', ['username' => $username]);
登入後複製
Further formatting of message parameters is supported using the PHPintl extensions message formatter. See yii\i18n\I18N::translate() formore details.
public static stringt ($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-US,en).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的組別,解析翻譯文件使用的是預設的類別yiii18nPhpMessageSource,翻譯檔案放置在common/messages下,翻譯檔案是common.php。

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

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

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

<?php  
return [  
    &#39;Signup&#39; => &#39;注册&#39;,  
    &#39;Login&#39; => &#39;登陆&#39;,  
    &#39;Logout&#39; => &#39;登出&#39;,  
    &#39;Home&#39; => &#39;首页&#39;,  
    &#39;Contact&#39; => &#39;反馈&#39;,  
    &#39;About&#39; => &#39;关于&#39;,  
];
登入後複製

然後我們在layouts文件裡做翻譯,在/views/layouts/main.

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

$menuItems = [  
        //[&#39;label&#39; => &#39;Home&#39;, &#39;url&#39; => [&#39;/site/index&#39;]],  
        //[&#39;label&#39; => &#39;About&#39;, &#39;url&#39; => [&#39;/site/about&#39;]],  
        //[&#39;label&#39; => &#39;Contact&#39;, &#39;url&#39; => [&#39;/site/contact&#39;]],  
        [&#39;label&#39; => \Yii::t(&#39;common&#39;, &#39;Home&#39;), &#39;url&#39; => [&#39;/site/index&#39;]],  
        [&#39;label&#39; => \Yii::t(&#39;common&#39;, &#39;About&#39;), &#39;url&#39; => [&#39;/site/about&#39;]],  
        [&#39;label&#39; => \Yii::t(&#39;common&#39;, &#39;Contact&#39;), &#39;url&#39; => [&#39;/site/contact&#39;]],  
    ];
登入後複製

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

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

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


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

在common/config/main-local.php裡,加入以下設定:

<?php  
return [  
   &#39;language&#39; => &#39;zh-CN&#39;,  
   ...  
];
登入後複製

再檢查一下是否生效。

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


可以看到翻譯已經生效。

但用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。

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

2.在/common/config/main-local.php裡配置可用的語言,供我們在控制項中呼叫

<?php  
return [  
    &#39;language&#39; => &#39;zh-CN&#39;,  
  
    &#39;components&#39; => [  
        ...  
    ],  
    &#39;params&#39; => [  
        &#39;availableLanguages&#39; => [  
            &#39;zh-CN&#39; => [&#39;img&#39; => &#39;image/zh.png&#39;, &#39;desc&#39; => &#39;中文&#39;],  
            &#39;en-US&#39; => [&#39;img&#39; => &#39;image/en.png&#39;, &#39;desc&#39; => &#39;English&#39;],  
        ],  
    ],  
    ...  
];
登入後複製

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[&#39;availableLanguages&#39;];
		$isMatch = false;
		foreach ($avLang as $key => $value) {
			if($key == $lang) {
				$tag = LanguageSelector::buildImgTag($value[&#39;img&#39;], $value[&#39;desc&#39;]);
				$isMatch = true;
			}
		}
		if(!$isMatch) {
			$tag = LanguageSelector::buildImgTag($avLang[0][&#39;img&#39;], $avLang[0][&#39;desc&#39;]);
		}
		$return = [
			&#39;label&#39; => $tag, 
			&#39;items&#39; => LanguageSelector::buildMenuItems($avLang),
		];
		
		return $return;
	}	
	
	private static function buildImgTag($src, $desc)
	{
		return &#39;<img src="&#39; . $src . &#39;" alt="&#39; . $desc . &#39;">&#39;;
	}
	
	private static function buildMenuItems($langs)
	{
		foreach ($langs as $key => $value) {
			$link = Html::a(LanguageSelector::buildImgTag($value[&#39;img&#39;], $value[&#39;desc&#39;]) . &#39; &#39; . $value[&#39;desc&#39;], Url::home(), [
					&#39;title&#39; => LanguageSelector::buildImgTag($value[&#39;img&#39;], $value[&#39;desc&#39;]) . &#39; &#39; . $value[&#39;desc&#39;],
					&#39;onclick&#39;=>"
					     $.ajax({
					    type     :&#39;POST&#39;,
					    cache    : false,
					    url  : &#39;" . Url::toRoute("ajax/lang") . "&#39;,
						data: { _lang : &#39;" . $key . "&#39; },
					    success  : function(response) {
					        window.location.reload();
					    }
					    });return false;",
			]);
			$menuItems[] = &#39;<li>&#39; . $link . &#39;</li>&#39;;
		}
		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[&#39;_lang&#39;]))
		{
			$lang = SelectLanguageBehavior::getSelectedLanguage($_POST[&#39;_lang&#39;]);
			Yii::$app->language = $lang;
			$cookie = new cookie([
					&#39;name&#39; => &#39;_lang&#39;,
					&#39;value&#39; => $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 => &#39;beforeRequest&#39;,
		];
	}
	
	public function beforeRequest($event) {
		$app = Yii::$app;
	
		$lang = SelectLanguageBehavior::getSelectedLanguage(Yii::$app->request->cookies->getValue(&#39;_lang&#39;));
		$app->language = $lang;
	}
	
	public static function getSelectedLanguage($val) {
		$langs = Yii::$app->params[&#39;availableLanguages&#39;];
		foreach ($langs as $key=>$value) {
			if($val == $key) {
				return $val;
			}
		}
		return key($langs);
	}
}
登入後複製

6.將該動作綁定到系統中。

在common/config/main-local.php中加入as beginRequest項目

<?php  
return [  
    &#39;language&#39; => &#39;zh-CN&#39;,  
  
    &#39;components&#39; => [  
        ...  
    ],  
    ...  
    &#39;as beginRequest&#39; => [  
            &#39;class&#39; => &#39;common\components\SelectLanguageBehavior&#39;,  
    ],  
];
登入後複製

7.將該控制項加入到頁面上。

在frontend/views/layouts/main.php裡,添加代碼顯示我們的控件,因為控件中帶html代碼,還要防止它做轉義處理

...
    if (Yii::$app->user->isGuest) {
        $menuItems[] = [&#39;label&#39; => Yii::t(&#39;common&#39;, &#39;Signup&#39;), &#39;url&#39; => [&#39;/site/signup&#39;]];
        $menuItems[] = [&#39;label&#39; => Yii::t(&#39;common&#39;, &#39;Login&#39;), &#39;url&#39; => [&#39;/site/login&#39;]];
    } else {
        $menuItems[] = [
            &#39;label&#39; => Yii::t(&#39;common&#39;, &#39;Logout&#39;) . &#39; (&#39; . Yii::$app->user->identity->username . &#39;)&#39;,
            &#39;url&#39; => [&#39;/site/logout&#39;],
            &#39;linkOptions&#39; => [&#39;data-method&#39; => &#39;post&#39;]
        ];
    }
	
	// add this line
        $menuItems[] = \common\widgets\LanguageSelector::getMenu();
	
	echo Nav::widget([
        &#39;options&#39; => [
        	&#39;class&#39; => &#39;navbar-nav navbar-right&#39;,
        	],
        &#39;items&#39; => $menuItems,
        // add this line
    	&#39;encodeLabels&#39; => false,
    ]);
	...
登入後複製
8.打開頁面查看效果

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


 以上就是Yii2 framework學習筆記(三) -- 語言與國際化的內容,更多相關內容請關注PHP中文網(www.php.cn)!


🎜
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板