Yii2根据所选语言更改控制器和操作名称

时间:2016-07-24 13:33:18

标签: yii2 yii2-advanced-app

是否可以使用当前选择的语言更改控制器名称和操作名称,如:

如果当前语言是en,则url shuold:

http://localhost/yii2app/site/index

如果当前语言是da,则url应该:

http://localhost/yii.../websted/indeks

  
    

这是我尝试过的,但它显示404未找到:

  

前端/配置/ main.php

'urlManager' => [
        'baseUrl' => $baseUrl,
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [
            Yii::t('app','site/index') => Yii::t('app','site/index'),
        ],
 ],

共同/ messages / da / app.php

 return [
         'site/index'=>'websted/indeks'
 ];

在我的布局/ main.php

  <a href="<?= Yii::$app->urlManager
                  ->createUrl([Yii::t('app','site/index')])?>">
      <?= Yii::t('app','Home') ?>
  </a>

2 个答案:

答案 0 :(得分:3)

我已从Yii论坛修改此代码以使用当前框架版本。它需要进行测试,因为我非常确定不是每个案例都包含在那里。

常见\部件\ UrlManager.php:

<?php

namespace common\components;

use Yii;
use yii\web\Request;
use yii\web\UrlManager as YiiUrlManager;

/**
 * UrlManager
 * Allows to translate urls dynamically.
 */
class UrlManager extends YiiUrlManager
{
    public $enablePrettyUrl = true;
    public $showScriptName  = false;

    public $language;

    /**
     * Translated controllers names.
     * language code => [
     *      source name => translated name
     * ]
     * @var array 
     */
    public $languageControllers = [
        'eo' => [
            'site'  => 'ejo',
            'users' => 'uzantoj'
        ],
    ];

    /**
     * Translated actions names.
     * language code => [
     *      source name => translated name
     * ]
     * @var array 
     */
    public $languageActions = [
        'eo' => [
            'contact' => 'kontakton',
            'about'   => 'pri-ni',
            'test'    => 'testo'
        ],
    ];

    /**
     * Initializes UrlManager.
     */
    public function init()
    {
        parent::init();

        if (empty($this->language)) {
            $this->language = Yii::$app->language;
        }
    }

    /**
     * Creates translated url.
     * @param array $params
     * @return string the created URL
     */
    public function createUrl($params)
    {
        $params = (array)$params;

        $route = explode('/', trim($params[0], '/'));
        if (isset($route[0]) && !empty($this->languageControllers[$this->language][$route[0]])) {
            $route[0] = $this->languageControllers[$this->language][$route[0]];
        }
        if (isset($route[1]) && !empty($this->languageActions[$this->language][$route[1]])) {
            $route[1] = $this->languageActions[$this->language][$route[1]];
        }
        $params[0] = implode('/', $route);

        return parent::createUrl($params);
    }

    /**
     * Translates the request back to the source one.
     * @param Request $request the request component
     * @return Request
     */
    public function translateRequest($request)
    {
        if (empty($this->languageControllers[$this->language])) {
            return $request;
        }
        $url = ltrim($request->getPathInfo(), '/');
        $parts = explode('/', $url);
        $controller = $parts[0];
        $action = isset($parts[1]) ? $parts[1] : null;
        foreach ($this->languageControllers[$this->language] as $default => $localized) {
            if ($localized == $controller) {
                $controller = $default;
                break;
            }
        }
        $parts[0] = $controller;
        if ($action !== null) {
            foreach ($this->languageActions[$this->language] as $default => $localized) {
                if ($localized === substr($action, 0, mb_strlen($localized, 'UTF-8'))) {
                    $action = $default . substr($action, mb_strlen($localized, 'UTF-8'));
                    break;
                }
            }
            $parts[1] = $action;
        }
        $request->setPathInfo(implode('/', $parts));
        return $request;
    }

    /**
     * Parses and translates the user request.
     * @param Request $request the request component
     * @return array|boolean the route and the associated parameters. The latter is always empty
     * if [[enablePrettyUrl]] is false. False is returned if the current request cannot be successfully parsed.
     */
    public function parseRequest($request)
    {
        return parent::parseRequest($this->translateRequest($request));
    }
}

UrlManager配置:

// ...
'components' => [
    // ...
    'urlManager' => [
        'class' => 'common\components\UrlManager',
        // ...
    ],
],

现在,对于Yii:$ app-&gt; language =&#39; eo&#39;;

  1. / site / test调用控制器Site with action test。
  2. / ejo / testo调用控制器站点并执行操作测试。
  3. / ejo使用操作索引调用控制器站点。
  4. / site / testo调用控制器站点并执行操作测试。
  5. 对于不同语言,只有现有路线有效。您可以以正常方式将参数发送到操作。

答案 1 :(得分:1)

您的代码无法运行,因为当yii2加载您的配置时,它没有Yii实例。

我对你的问题有2个想法。希望它有用。

1:使用redirect

示例:

public function actionIndex()
{
    if(Yii::$app->language === 'da')
        return $this->redirect(['websted/indeks']);
    else
        return $this->redirect(['site/index']);
}

当用户请求site/index时,yii将重定向到您的语言的其他链接。当语言为@baseUrl/websted/indeks时,浏览器中的地址将更改为da。但是,只要您的应用中有新语言,就必须定义和更改代码。

<强> 2。在bootstrap设置rule

配置:

'bootstrap' => [
    'log',
    [
        'class' => 'app\components\Bootstrap',
    ],
],

bootstrap.php中

namespace app\components;

use Yii;
use yii\base\BootstrapInterface;

class Bootstrap implements BootstrapInterface
{

    public function bootstrap($app)
    {
        $app->urlManager->addRules(['site/test' => Yii::t('app','site/test')]);
    }
}

语言1,app.php

return [
    'site/test'=>'site/test1',
];

语言2,app.php

return [
    'site/test'=>'site/test2',
];

控制器(示例SiteController):

public function actionTest1()
{
    echo 1;
}

public function actionTest2()
{
    echo 2;
}

但问题是:当用户请求site/test时,yii会检查语言并运行操作test1test2,并且浏览器中的地址仅为@baseUrl/site/test

enter image description here

Goodluck,玩得开心!