Yii和多语言URL


Yii and multilingual URLs

我正在尝试创建多语言应用程序。我已经实现了可翻译内容的能力,下一步应该是向用户展示它。我想拥有根据URL更改语言的能力。我已经找到了几个用于这些目的的组件,但它们都创建了我不喜欢的url。例如,我的应用程序的默认语言是英语,我有翻译成法语的内容。例如,我有"联系人"页面。应用程序将生成的URL为:mysite.com/en/contacts、mysite.com/fr/contacts,但我希望默认语言为mysite.com/contacts,法语为mysite.com.cn/fr/contacts。它也类似于网站的根。mysite.com/-表示默认语言,mysite.com/fr表示法语。有没有实现这些功能的方法?

我在GitHub 上使用XUrlManager扩展XUrlManager

Yii根据UrlManager规则生成URL。如果你想要没有/lang/code的URL,你只需要创建正确的规则。例如,如果您复制规则数组中的记录:

'rules'=>array(
    '<_c:'w+>/<_a:'w+>'=>'<_c>/<_a>',
    '<language:'w{2}>/<_c:'w+>/<_a:'w+>'=>'<_c>/<_a>',
);

您的URL将使用ou/en/和/fr/生成,但带有代码的URL也可以工作。默认情况下,XUrlManager使用以前选择的语言,并将其存储在会话或cookie中。

如果你只想隐藏/en/并始终使用/fr/和其他,你可以用更改你的XUrlManager扩展

public function createUrl($route,$params=array(),$ampersand='&')
{
    if(!isset($params['language']) && Yii::app()->language!=='en')
        $params['language']=Yii::app()->language;
    return parent::createUrl($route,$params,$ampersand);
}

我在http://www.elisdn.ru

重新实现CHttpRequest

class DLanguageHttpRequest extends CHttpRequest
{
    private $_requestUri;
    public function getRequestUri()
    {
        if ($this->_requestUri === null)
            $this->_requestUri = DMultilangHelper::processLangInUrl(parent::getRequestUri());
        return $this->_requestUri;
    }
    public function getOriginalUrl()
    {
        return $this->getOriginalRequestUri();
    }
    public function getOriginalRequestUri()
    {
        return DMultilangHelper::addLangToUrl($this->getRequestUri());
    }
}

重新实现CUrlManager

class DLanguageUrlManager extends CUrlManager
{
    public function createUrl($route, $params=array(), $ampersand='&')
    {
        $url = parent::createUrl($route, $params, $ampersand);
        return DMultilangHelper::addLangToUrl($url);
    }
}

更改配置

return array(
    'sourceLanguage'=>'en',
    'language'=>'ru',
    'components'=>array(
        'request'=>array(
            'class'=>'DLanguageHttpRequest',
            ...
        ),
        'urlManager'=>array(
            'class'=>'DLanguageUrlManager',
            ...
        ),
    ),
    ...
    'params'=>array(
        'translatedLanguages'=>array(
            'ru'=>'Russian',
            'en'=>'English',
            'de'=>'Deutsch',
        ),
        'defaultLanguage'=>'ru',
    ),
);

创建DMultilangHelper

class DMultilangHelper
{
    public static function enabled()
    {
        return count(Yii::app()->params['translatedLanguages']) > 1;
    }
    public static function suffixList()
    {
        $list = array();
        $enabled = self::enabled();
        foreach (Yii::app()->params['translatedLanguages'] as $lang => $name)
        {
            if ($lang === Yii::app()->params['defaultLanguage']) {
                $suffix = '';
                $list[$suffix] = $enabled ? $name : '';
            } else {
                $suffix = '_' . $lang;
                $list[$suffix] = $name;
            }
        }
        return $list;
    }
    public static function processLangInUrl($url)
    {
        if (self::enabled())
        {
            $domains = explode('/', ltrim($url, '/'));
            $isLangExists = in_array($domains[0], array_keys(Yii::app()->params['translatedLanguages']));
            $isDefaultLang = $domains[0] == Yii::app()->params['defaultLanguage'];
            if ($isLangExists && !$isDefaultLang)
            {
                $lang = array_shift($domains);
                Yii::app()->setLanguage($lang);
            }
            $url = '/' . implode('/', $domains);
        }
        return $url;
    }
    public static function addLangToUrl($url)
        if (self::enabled())
        {
            $domains = explode('/', ltrim($url, '/'));
            $isHasLang = in_array($domains[0], array_keys(Yii::app()->params['translatedLanguages']));
            $isDefaultLang = Yii::app()->getLanguage() == Yii::app()->params['defaultLanguage'];
            if ($isHasLang && $isDefaultLang)
                array_shift($domains);
            if (!$isHasLang && !$isDefaultLang)
                array_unshift($domains, Yii::app()->getLanguage());
            $url = '/' . implode('/', $domains);
        }
        return $url;
    }
}

完成所有这些步骤后,您的应用程序将具有您想要的URL更多信息请点击此处