使用 angular 和 yii2 实现多语言应用程序的最佳方法是什么
What is the best approach to implement multi language app using angular and yii2
我正在使用 yii2 restful api 作为后端,angular 作为前端。
我想问一下实现多语言功能的最佳方法,该功能可以在同一个地方(db table、文件)管理前端和后端。
理论和指南:
要在 Yii2 应用程序中实现|启用 multi-language 功能,您应该使用 i18n
组件 https://www.yiiframework.com/doc/guide/2.0/en/tutorial-i18n.
接下来是检测frontend
|backend
|api
请求|要求|选择了哪种语言。这可以通过多种方式完成:headers、cookies、session、get、post 甚至通过主机名。
在处理请求之前,您需要通过某种优先级检测所选语言,语言配置存储在哪里并将其设置为应用程序。
代码:
app/common/config/main.php
return [
// ...
'language' => 'en', // base language
// ...
'components' => [
//...
'i18n' => [
'translations' => [
'*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/messages',
'sourceLanguage' => 'en',
],
],
],
// ...
],
// ...
// handle request and detect language
'as beforeRequest' => [
'class' => app\common\behaviours\LanguageHandler::class,
],
app/common/behaviours/LanguageHandler.php
namespace common\behaviours;
use common\models\User;
use Yii;
use yii\base\Behavior;
use yii\base\Event;
use yii\helpers\Url;
use yii\web\Application;
use yii\web\Cookie;
/**
* Class LanguageHandler
* @package common\behaviours
*/
class LanguageHandler extends Behavior
{
const LANG_KEY = 'language';
public $domainOnly = false;
/**
* @return array
*/
public function events()
{
return [
Application::EVENT_BEFORE_REQUEST => 'handleBeginRequest',
];
}
/**
* Handle app selected language
*
* Priority of detecting language
* 1) Detect from host name
* 2) Detect from post
* 3) Detect from headers
* 4) Detect from cookies
* 5) Detect from user config
* 6) Use default app language
*
* @param Event $event
*/
public function handleBeginRequest(Event $event)
{
$hostName = $request->getHostName();
$request = Yii::$app->getRequest();
$language = $request->post(self::LANG_KEY, null);
$query = $request->getQueryParams();
$cookies = $request->getCookies();
$headers = $request->getHeaders();
/**
* Try first by domain and hostname
*/
if ($this->domainOnly) {
/**
* Try first by domain and hostname
*/
if (substr($hostName, -3) == '.ru') {
$language = 'ru';
} else {
$language = 'en';
}
} else {
if (substr($hostName, -3) == '.ru') {
$language = 'ru';
}
}
/**
* Use detected language or try to get language from query params
*/
$language = $language ?? ($query[self::LANG_KEY] ?? null);
/**
* Use detected language or try to get language from request headers
*/
$language = $language ?? (
$headers->has(self::LANG_KEY)
? (
array_key_exists($headers->get(self::LANG_KEY), Yii::$app->params['languages'])
? $headers->get(self::LANG_KEY)
: null
)
: null
);
/**
* Use detected language or try to get language from cookies headers
*/
$language = $language ?? (
$cookies->has(self::LANG_KEY)
? (
array_key_exists($cookies->getValue(self::LANG_KEY), Yii::$app->params['languages'])
? $cookies->getValue(self::LANG_KEY)
: null
)
: null
);
/**
* Use detected language or try to get language from user profile
*/
if (empty($language) && !Yii::$app->user->isGuest) {
/** @var User $user */
$user = Yii::$app->user->identity;
if ($user instanceof User && isset($user->language) && !empty($user->language)) {
$language = $user->language;
}
}
/**
* If no language use default
*/
$language = $language ?? Yii::$app->language;
// Add a cookie for next requests
$languageCookie = new Cookie([
'name' => self::LANG_KEY,
'value' => $language,
'expire' => time() + 86400 * 365,
]);
Yii::$app->getResponse()->getCookies()->add($languageCookie);
// store selected language to application
Yii::$app->language = $language;
}
}
现在您可以使用它来实现您的目标,还可以建立检测语言的优先级。
从 Angular
开始,您可以为请求设置 language
header。
const headers = {
'Accept': '*/*',
'Content-Type': 'multipart/form-data;',
'X-Requested-With': 'XMLHttpRequest',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Origin': '*',
'language': 'en'
}
我正在使用 yii2 restful api 作为后端,angular 作为前端。
我想问一下实现多语言功能的最佳方法,该功能可以在同一个地方(db table、文件)管理前端和后端。
理论和指南:
要在 Yii2 应用程序中实现|启用 multi-language 功能,您应该使用
i18n
组件 https://www.yiiframework.com/doc/guide/2.0/en/tutorial-i18n.接下来是检测
frontend
|backend
|api
请求|要求|选择了哪种语言。这可以通过多种方式完成:headers、cookies、session、get、post 甚至通过主机名。在处理请求之前,您需要通过某种优先级检测所选语言,语言配置存储在哪里并将其设置为应用程序。
代码:
app/common/config/main.php
return [
// ...
'language' => 'en', // base language
// ...
'components' => [
//...
'i18n' => [
'translations' => [
'*' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@common/messages',
'sourceLanguage' => 'en',
],
],
],
// ...
],
// ...
// handle request and detect language
'as beforeRequest' => [
'class' => app\common\behaviours\LanguageHandler::class,
],
app/common/behaviours/LanguageHandler.php
namespace common\behaviours;
use common\models\User;
use Yii;
use yii\base\Behavior;
use yii\base\Event;
use yii\helpers\Url;
use yii\web\Application;
use yii\web\Cookie;
/**
* Class LanguageHandler
* @package common\behaviours
*/
class LanguageHandler extends Behavior
{
const LANG_KEY = 'language';
public $domainOnly = false;
/**
* @return array
*/
public function events()
{
return [
Application::EVENT_BEFORE_REQUEST => 'handleBeginRequest',
];
}
/**
* Handle app selected language
*
* Priority of detecting language
* 1) Detect from host name
* 2) Detect from post
* 3) Detect from headers
* 4) Detect from cookies
* 5) Detect from user config
* 6) Use default app language
*
* @param Event $event
*/
public function handleBeginRequest(Event $event)
{
$hostName = $request->getHostName();
$request = Yii::$app->getRequest();
$language = $request->post(self::LANG_KEY, null);
$query = $request->getQueryParams();
$cookies = $request->getCookies();
$headers = $request->getHeaders();
/**
* Try first by domain and hostname
*/
if ($this->domainOnly) {
/**
* Try first by domain and hostname
*/
if (substr($hostName, -3) == '.ru') {
$language = 'ru';
} else {
$language = 'en';
}
} else {
if (substr($hostName, -3) == '.ru') {
$language = 'ru';
}
}
/**
* Use detected language or try to get language from query params
*/
$language = $language ?? ($query[self::LANG_KEY] ?? null);
/**
* Use detected language or try to get language from request headers
*/
$language = $language ?? (
$headers->has(self::LANG_KEY)
? (
array_key_exists($headers->get(self::LANG_KEY), Yii::$app->params['languages'])
? $headers->get(self::LANG_KEY)
: null
)
: null
);
/**
* Use detected language or try to get language from cookies headers
*/
$language = $language ?? (
$cookies->has(self::LANG_KEY)
? (
array_key_exists($cookies->getValue(self::LANG_KEY), Yii::$app->params['languages'])
? $cookies->getValue(self::LANG_KEY)
: null
)
: null
);
/**
* Use detected language or try to get language from user profile
*/
if (empty($language) && !Yii::$app->user->isGuest) {
/** @var User $user */
$user = Yii::$app->user->identity;
if ($user instanceof User && isset($user->language) && !empty($user->language)) {
$language = $user->language;
}
}
/**
* If no language use default
*/
$language = $language ?? Yii::$app->language;
// Add a cookie for next requests
$languageCookie = new Cookie([
'name' => self::LANG_KEY,
'value' => $language,
'expire' => time() + 86400 * 365,
]);
Yii::$app->getResponse()->getCookies()->add($languageCookie);
// store selected language to application
Yii::$app->language = $language;
}
}
现在您可以使用它来实现您的目标,还可以建立检测语言的优先级。
从 Angular
开始,您可以为请求设置 language
header。
const headers = {
'Accept': '*/*',
'Content-Type': 'multipart/form-data;',
'X-Requested-With': 'XMLHttpRequest',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Origin': '*',
'language': 'en'
}