Question

I'm trying to create multilingual application. I've implemented ability of translationable content and next step should be showing it to user. I want to have ability of changing language depending on URL. I've found a couple of components for those purposes but they all create urls which I don't like. For example, my application's default language is English and I have content which is translated into French. I have page "contacts", for instance. And URLs which will be generated by application will be: mysite.com/en/contacts, mysite.com/fr/contacts, but I want to have mysite.com/contacts for default language and mysite.com/fr/contacts for French language. It's simillar for site's root too. mysite.com/ - for default language and mysite.com/fr for French. Is there any methods for implementing these functionality?

Was it helpful?

Solution 2

I've found very elegant method for solving my problem on http://www.elisdn.ru

Reimplement 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());
    }
}

Reimplement CUrlManager

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

Change config

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',
    ),
);

Create 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;
    }
}

After all of these steps your application will have URLs which you want More information here

OTHER TIPS

I'm using XUrlManager extension XUrlManager on GitHub

Yii generates URL's based on UrlManager rules. If you want URL's without /lang/ code - you need just create correct rules. For example, if you dublicate records in rules array:

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

your URL's will be generated withou /en/ and /fr/, but URL's with code works too. By default, XUrlManager use previously selected language and store this in session or cookie.

If you want only hide /en/ and use /fr/ and others always, you can change your XUrlManager extension with:

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);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top