LangUrlManager

Выкладываем свои наработки
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

LangUrlManager

Сообщение Ekstazi »

Выложил свой маленький компонент на основе стандартного urlManager а.

Позволяет передавать язык приложения(а отсюда и менять) через параметр(динамически задается), указаный в конфиге.
К примеру, все ссылки могут быть вида:
http://my.everwork.org/doska/index.php? ... ut&lang=ru
или
http://my.everwork.org/kabinet/index.ph ... in&lang=en
или даже
http://serlina.org/ro/price/new
Достаточно лишь правильно указать правила парсинга ссылок и указать имя переменой для задания языка.
Это префинальная версия. Изменений пока не планируется.

Лежит тут:
http://www.yiiframework.com/extension/langurlmanager/

В дальнейшем возможно выложу еще пару расширений для мнгогоязычных приложений.
Аватара пользователя
Stepan Selyuk
Сообщения: 198
Зарегистрирован: 2010.02.03, 05:51
Откуда: Cyprus, Limassol
Контактная информация:

Re: LangUrlManager

Сообщение Stepan Selyuk »

Я тоже столкнулся с проблемой передачи языкового параметра, но сделал по другому (сейчас увидел ваше расширение, и конечно удобнее использовать его).
Создал базовый контроллер от которого наследую контроллеры приложения:

Код: Выделить всё

class AppController extends CController {

    /**
     * @var array the breadcrumbs of the current page. The value of this property will
     * be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links}
     * for more details on how to specify this property.
     */
    public $breadcrumbs = array ();

    function init () {

        parent::init();
        
        $app = Yii::app();
        if ( isset($_GET['lang']) ) {
            
            $app->setLanguage($_GET['lang']);
            $app->session['lang'] = $app->getLanguage();
        
        } else if ( isset($app->session['lang']) ) {
            $app->setLanguage($app->session['lang']);
        } else {
            $app->setLanguage('ru');
            $app->session['lang'] = $app->getLanguage();
        }
    
    }

    // --------------------------------------------------------------------------------------------------------------------
    

    public function createAbsoluteUrl ($route, $params = array(), $schema = '', $ampersand = '&') {

        $app = Yii::app();
        if ( $app->language !== $app->sourceLanguage ) $params = array_merge($params, array ('lang' => $app->language));
        return parent::createAbsoluteUrl($route, $params, $schema, $ampersand);
    }

    // --------------------------------------------------------------------------------------------------------------------
    

    public function createUrl ($route, $params = array(), $ampersand = '&') {

        $app = Yii::app();
        if ( $app->language !== $app->sourceLanguage ) $params = array_merge($params, array ('lang' => $app->language));
        
        return parent::createUrl($route, $params, $ampersand);
    
    }
}
 
Это можно убрать (сделал для себя).

Код: Выделить всё

if ( $app->language !== $app->sourceLanguage )
 
Естественно, Ваше решение шире и позволяет использовать Yii::app()->getUrlManager()->createUrl(), а мое не позволяет. Если только передавать параметром язык.
Сначала невидимое, затем видимое. И так у всех программистов :)
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: LangUrlManager

Сообщение Ekstazi »

Обновил версию, теперь корректно разбирает параметры в path формате.
Качать тут http://www.yiiframework.com/extension/langurlmanager/
P.S.:на svn выложу как будет больше времени
Аватара пользователя
Tokolist
Сообщения: 113
Зарегистрирован: 2010.03.01, 22:03

Re: LangUrlManager

Сообщение Tokolist »

имхо использовать parsePathInfo не красиво, поскольку он может вызываться по несколько раз, а иногда и вовсе не вызывается

я пошел другим путем, когда обнаружил проблему с path

Код: Выделить всё

<?php

class LangUrlManager extends CUrlManager
{
    public $languages=array('en');
    public $langParam='lang';

    public function setAppLanguage()
    {
        $userLang=Yii::app()->getRequest()->getPreferredLanguage();
        //if language pass via url use it
        if(isset($_GET[$this->langParam])&&in_array($_GET[$this->langParam],$this->languages)){
            Yii::app()->language=$_GET[$this->langParam];
        //else if preffered language is allowed
        }elseif(in_array($userLang,$this->languages)) {
            Yii::app()->language=$userLang;
        //else use the first language from the list
        }else Yii::app()->language=$this->languages[0];
    }

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

        return parent::createUrl($route,$params,$ampersand);
    }

    public function createLangUrl($language, $ampersand='&')
    {
        $route = Yii::app()->controller->route;
        $params = $_GET;
        unset($params[$this->routeVar]);
        $params[$this->langParam] = $language;
        return parent::createUrl($route,$params,$ampersand);
    }

}
 
а в protected/components/Controller.php

Код: Выделить всё

    public function init()
    {
        parent::init();
        Yii::app()->urlManager->setAppLanguage();
    } 
Кстати, там у меня еще один метод createLangUrl, который написал для создания языковых ссылок.
У него есть только проблема создания ссылок при обработке ошибок, т.к. там роут site/error (по умолчанию), хотя в урле другой адрес.
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: LangUrlManager

Сообщение Ekstazi »

Хорошо, добавлю оптимизацию при разборе языка.
AbS_
Сообщения: 207
Зарегистрирован: 2010.03.27, 14:02

Re: LangUrlManager

Сообщение AbS_ »

Код: Выделить всё

        Yii::app()->urlManager->setAppLanguage(); 
А почему это не вынести в init() метод LangUrlManager'a?
Я так понимаю что этот метод вызывает всегда. http://www.yiiframework.com/doc/api/CUr ... nit-detail
Или я что то не понял?
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: LangUrlManager

Сообщение Ekstazi »

А если формат ссылок PATH то язык не отпарсится из ссылки (
Аватара пользователя
Tokolist
Сообщения: 113
Зарегистрирован: 2010.03.01, 22:03

Re: LangUrlManager

Сообщение Tokolist »

AbS_ писал(а):

Код: Выделить всё

        Yii::app()->urlManager->setAppLanguage(); 
А почему это не вынести в init() метод LangUrlManager'a?
Я так понимаю что этот метод вызывает всегда. http://www.yiiframework.com/doc/api/CUr ... nit-detail
Или я что то не понял?
К сожалению, так не получится. Надо что-бы предварительно $_GET заполнился исходя из ссылки в path-формате.
Аватара пользователя
Tokolist
Сообщения: 113
Зарегистрирован: 2010.03.01, 22:03

Re: LangUrlManager

Сообщение Tokolist »

Жаль, что у CWebApplication нет какого-нибудь подходящего события...
Аватара пользователя
Tokolist
Сообщения: 113
Зарегистрирован: 2010.03.01, 22:03

Re: LangUrlManager

Сообщение Tokolist »

Добавил возможность запоминания языка в кукиз.
Для этого надо просто задать название куки в свойстве langCookieName

Код: Выделить всё

<?php
/**
  * This extension allows you to pass the application language via an url
  * and then use it for all further generated urls.
  * @author Ekstazi http://yii-blog.blogspot.com
  * @author Pelesh Yaroslav aka Tokolist http://tokolist.com
  * @version 1.0
  */

class LangUrlManager extends CUrlManager
{
    public $languages=array('en');
    public $langParam='lang';
    public $langCookieName=false;

    protected function getCookieLang()
    {
        $cookieLang = false;

        if(!empty($this->langCookieName))
        {
            $cookies = Yii::app()->getRequest()->getCookies();
            
            if(isset($cookies[$this->langCookieName]))
            {
                $cookieLang = $cookies[$this->langCookieName]->value;
            }
        }
        
        return $cookieLang;
    }

    protected function setCookieLang()
    {
        if(!empty($this->langCookieName))
        {
            $cookies = Yii::app()->getRequest()->getCookies();

            if(!isset($cookies[$this->langCookieName]) 
                || $cookies[$this->langCookieName]->value != Yii::app()->language)
            {
                $cookie = new CHttpCookie($this->langCookieName,Yii::app()->language);
                $cookie->expire = time() + 60*60*24*365; //1 year

                $cookies[$this->langCookieName] = $cookie;
            }
        }
    }

    protected function getPreferredLang()
    {
        return Yii::app()->getRequest()->getPreferredLanguage();
    }

    public function setAppLanguage()
    {
        //If language pass via url use it
        if(isset($_GET[$this->langParam]) && in_array($_GET[$this->langParam],$this->languages))
        {
            Yii::app()->language = $_GET[$this->langParam];
        }
        //Else if lang cookie is setted
        elseif(in_array($cookieLang=$this->getCookieLang(),$this->languages))
        {
            Yii::app()->language = $cookieLang;
        }
        //Else if preffered language is allowed
        elseif(in_array($prefferedLang=$this->getPreferredLang(),$this->languages))
        {
            Yii::app()->language = $prefferedLang;
        }
        //Else use the first language from the list
        else
        {
            Yii::app()->language = $this->languages[0];
        }

        //Remember lang in cookies
        $this->setCookieLang();
    }

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

        return parent::createUrl($route,$params,$ampersand);
    }

    public function createLangUrl($language, $ampersand='&')
    {
        $route = Yii::app()->controller->route;
        $params = $_GET;
        unset($params[$this->routeVar]);
        $params[$this->langParam] = $language;
        return parent::createUrl($route,$params,$ampersand);
    }

} 
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: LangUrlManager

Сообщение Ekstazi »

Отлично, в следующем релизе учту
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: LangUrlManager

Сообщение slavcodev »

Tokolist писал(а):Жаль, что у CWebApplication нет какого-нибудь подходящего события...

Код: Выделить всё

'onBeginRequest'=>function($event){
  $urlManager=Yii::app()->getUrlManager();
  $request=Yii::app()->getRequest();
  if($urlManager->urlFormat===CUrlManager::PATH_FORMAT){
    $pathInfo=$request->getPathInfo();
    $urlManager->parsePathInfo($urlManager->removeUrlSuffix($pathInfo,$urlManager->urlSuffix));
  }
  Yii::app()->language=$request->getQuery('langVar');
        
  return true;
}, 
можно так.
Жду Yii 3!
Аватара пользователя
Tokolist
Сообщения: 113
Зарегистрирован: 2010.03.01, 22:03

Re: LangUrlManager

Сообщение Tokolist »

mc-bear

Получается что у нас два раза будет разбор урла?...
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: LangUrlManager

Сообщение slavcodev »

Получается.
Я поспешил, написав не проверив, урл в onBeginRequest еще не очищен от контроллера, экшена и модуля,
а так же урл еще не прошел через правила, поэтому искать в этом евенте язык не стоит!
Жду Yii 3!
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: LangUrlManager

Сообщение slavcodev »

В контроллере есть beforeAction, жаль что нет евента onBeforeAction.
Жду Yii 3!
anti.mike
Сообщения: 14
Зарегистрирован: 2010.11.27, 11:54

Re: LangUrlManager

Сообщение anti.mike »

Подскажите, как использовать ЧПУ, если в системе используется Ваш компонент для переключения языка? В целом по системе передача параметров как поумолчанию в фреймворке, сам ничего дополнительно не цепляю нигде
Пробовал вот так но увы не работает

Код: Выделить всё

    'languages'=>array('ru','en','pl'),
                'langParam'=>'language',
                   'urlFormat' => 'path',
      'showScriptName' => false,
                 'rules' => array(
                     "<language:(ru|en|pl)>/<_c>/<_a>/*" => "<_c>/<_a>",
      ), 
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: LangUrlManager

Сообщение Ekstazi »

Код: Выделить всё

        'languages'=>array('ru','en','pl'),
                    'langParam'=>'language',
                       'urlFormat' => 'path',
          'showScriptName' => false,
                     'rules' => array(
                         "<language:(ru|en|pl)>/<_c>/<_a>" => "<_c>/<_a>",
          ),  
А так ?
anti.mike
Сообщения: 14
Зарегистрирован: 2010.11.27, 11:54

Re: LangUrlManager

Сообщение anti.mike »

Без изменений
Аватара пользователя
BuCeFaL
Сообщения: 447
Зарегистрирован: 2010.03.17, 21:22
Откуда: Kiev
Контактная информация:

Re: LangUrlManager

Сообщение BuCeFaL »

yiiframework.com лежит, если ли ссылка на репозиторий ?

зы: Спасибо за расширение !
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: LangUrlManager

Сообщение Ekstazi »

Хм, да я могу так кинуть, ща:

Код: Выделить всё

<?php
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of LangUrlManager
 *
 * @author Ekstazi
 * @ver 1.3
 */
class LangUrlManager extends CUrlManager{
    public $languages=array('en');
    public $langParam='lang';

    public function parsePathInfo($pathInfo)
    {
        parent::parsePathInfo($pathInfo);
        
        $userLang=Yii::app()->getRequest()->getPreferredLanguage();
        //if language pass via url use it
        if(isset($_GET[$this->langParam])&&in_array($_GET[$this->langParam],$this->languages)){
            Yii::app()->language=$_GET[$this->langParam];
        //else if preffered language is allowed
        }elseif(in_array($userLang,$this->languages)) {
            Yii::app()->language=$userLang;
        //else use the first language from the list
        }else Yii::app()->language=$this->languages[0];
    }
    //put your code here
    public function createUrl($route, $params=array(), $ampersand='&'){
        if(!isset($params[$this->langParam])&&Yii::app()->language!==Yii::app()->sourceLanguage) $params[$this->langParam]=Yii::app()->language;
        return parent::createUrl($route,$params,$ampersand);
    }
    //put your code here
}
 
Последняя версия. Её пока нигде нет.
Ответить