【发布时间】:2019-11-04 18:33:46
【问题描述】:
我需要创建用户友好的 URL,这些 URL 经过翻译,但指向与其他语言相同的控制器。
例子:
/en/myCar/100 -> /de/meinAuto/100 -> /fr/monVoiture/100
我尝试使用路由,但找不到根据翻译后的 URL 调用控制器的方法。
任何提示我应该从哪里开始?
【问题讨论】:
标签: routes translation yii2
我需要创建用户友好的 URL,这些 URL 经过翻译,但指向与其他语言相同的控制器。
例子:
/en/myCar/100 -> /de/meinAuto/100 -> /fr/monVoiture/100
我尝试使用路由,但找不到根据翻译后的 URL 调用控制器的方法。
任何提示我应该从哪里开始?
【问题讨论】:
标签: routes translation yii2
使用内置功能不容易做到这一点,但有人有同样的需求并专门为此编写了一个包:yii2-localeurls。我认为这可能是您正在寻找的:
使用此扩展程序,您可以使用包含以下语言代码的 URL:
/zh/some/page
/de/some/page
http://www.example.com/en/some/page
http://www.example.com/de/some/page如果需要,您还可以配置友好名称:
http://www.example.com/english/some/page
http://www.example.com/deutsch/some/page语言代码会在您创建 URL 时自动添加,并在解析 URL 时回读。为获得最佳用户体验,如果 URL 中未使用任何语言,则会从浏览器设置中自动检测语言。不过,用户仍然可以访问其他语言,只需调用带有另一种语言代码的 URL。
最后请求的语言也保留在用户会话和 cookie 中。因此,如果用户尝试在 URL 中没有语言代码的情况下访问您的网站,他将被重定向到他上次访问时使用的语言。
【讨论】:
这是我的工作解决方案,另外使用 https://github.com/codemix/yii2-localeurls 和 yii2 高级模板:
创建frontend/components/i18nUrlRules.php
namespace frontend\components;
use Yii;
use yii\base\BootstrapInterface;
class i18nUrlRules implements BootstrapInterface
{
public function bootstrap($app)
{
//Place here the translated UrlRules
$i18nRules=[
'myCar/index' => [
'de' => 'meinAuto',
'fr' => 'monVoiture',
'en' => 'myCar',
],
'...' => [
...
],
];
$reqLang=explode("/",$_SERVER['REQUEST_URI'])[1];
$languages = ['en','de','fr'];
$reqLang=in_array($reqLang,$languages)?$reqLang:\Yii::$app->language; //If not in array, use the default language
\Yii::$app->getUrlManager()->addRules(
[
$i18nRules['myCar/index'][$reqLang] =>'myCar/index',
...
],
false);
}
}
然后在frontend/config/main.php:
'bootstrap' => [
'log',
'frontend\components\i18nUrlRules',
],
所以,/en/myCar、/de/meinAuto 和 /fr/monVoiture 将使用 myCar/index 规则
【讨论】:
您可以在 Yii2 中手动轻松完成,无需任何扩展:
1) 在 config/web.php 里面改变你的规则(例如)
来自
'rules' =>[
[
'pattern' => '',
'route' => 'main/index',
'suffix' => ''
],
]
to(添加语言规则)
'rules' =>[
[
'pattern' => '',
'route' => 'main/index',
'suffix' => ''
],
'<language:\w{2}>'=>'main/index',
]
如果您有其他规则(例如),请对其他规则执行相同操作
[
'pattern' => '<controller>/<action>/<id:\w+>',
'route' => '<controller>/<action>',
'suffix' => ''
],
[
'pattern' => '<language:\w{2}>/<controller>/<action>/<id:\w+>',
'route' => '<controller>/<action>',
'suffix' => ''
],
2) 假设我们有 3 种语言:ru、en、kz。
所有控制器都扩展了我们的 BehaviorsController.php(例如,class MainController extends BehaviorsController)
在BehaviorsController.php里面创建beforeAction()函数
public function beforeAction($action)
{
$language = Yii::$app->getRequest()->getQueryParam('language');
if($language){
if(in_array($language,Yii::$app->params['langs'])) Yii::$app->session->set('lang',$language);
Yii::$app->language = $language;
}
return parent::beforeAction($action);
}
3) 在 config/params.php 中添加 langs 键到数组
return [
... // some params
'langs' => ['RU' => 'ru','KZ' => 'kz','EN' => 'en'], //allowed languages
];
4) 就是这样。现在我们可以使用语言参数检查路径:
example.com/ru
或
example.com/en
【讨论】:
好吧,事实证明,规则非常简单(一些尝试和错误有所帮助):
'<language:(de)>/meinAuto' => 'myCar/index',
'<language:(fr)>/monVoiture' => 'myCar/index'
...等等...
只是评论下面的答案:语言代码不是问题,我前段时间解决了这个问题......问题是,我需要用户语言的控制器部分
【讨论】:
对于任何提出这个问题的人, 看到这个包:Yii2 TranslatableUrlRule
因为这个包不是新的提交,所以使用Mohamed Amer这个fork
或直接使用this class 并将其复制到您的组件目录,然后执行这样的 url 规则:
在高级项目中,我在 common/components 目录中使用它。
'rules' => [
[
'class' => 'common\components\TranslatableUrlRule',
'patterns' => [
'ar' => 'مرحبا',
'en' => 'hi',
'en' => 'Hola',
],
'route' => '/main/hi',
],
【讨论】: