правильное использование языков в Zend Framework - PullRequest
5 голосов
/ 10 июня 2011

У меня есть приложение Zend с двумя модулями (admin и public), и для публичного доступа у меня есть следующий плагин для анализа моего friendly-url:

class Custom_Controller_Plugin_Initializer extends Zend_Controller_Plugin_Abstract {

    protected $_front;
    protected $_request;

    public function __construct() {
        $this->_front = Zend_Controller_Front::getInstance();
        $this->_request = $this->_front->getRequest();        
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
    //checking if the url ends with "/"      
        $requestUri = $this->_request->getRequestUri();
        $path = parse_url($requestUri, PHP_URL_PATH);
        $query = parse_url($requestUri, PHP_URL_QUERY);
        if (substr($path, -1) != '/') {
            header('location: ' . $path . (isset($query) ? '/?' . $query : '/'));
            die();
        }
// exploding the uri to get the parts.        
        $uri = explode('/', substr($path, strlen(Zend_Controller_Front::getInstance()->getBaseUrl()) + 1));


        $modelLanguage = new Model_Db_Language();
    //checking if the first part is of 2 characters and if it's a registered language
        if ($modelLanguage->checkLanguage($uri[0])) {            
            $language = $uri[0];
            unset($uri[0]); //deleting the language from the uri.
            $uri = array_values($uri);
        } else {
            $language = $modelLanguage->autoLanguage();
            if (!$uri[0] == '' && (strlen($uri[0]) == 2)) {
                $uri[0] = $language;
                header('location: ' . Zend_Controller_Front::getInstance()->getBaseUrl() . '/' . implode($uri) . (isset($query) ? '/?' . $query : '/'));
                die();
            }
        }

//remember that the language was deleted from the uri
        $this->_request->setParam('requestUri', implode('/', $uri));

        switch ($uri[0]) {
            case 'search':
                unset($uri[0]);
                $this->_request->setParam('s', urldecode($uri[2]));
                $this->_request->setModuleName('public');
                $this->_request->setControllerName('content');
                $this->_request->setActionName('search');
                $this->_request->setParam('template', 'search');
                break;
        }
        $this->_initTranslation($language);
            $this->_initInterface();
}}

Это очень полезно, если я хочу использовать такую ​​структуру, какdomain.com/en/about-us/mision/ потому что я могу разобрать URL и получить первый параметр "en" и после этого найти страницу, связанную с "about-us / mission", но что если я захочу использовать domain.com/en/user/profile/id/1/, Zend set " ru "в качестве контроллера и" пользователь"в качестве действия.Как я могу установить язык в URL и правильно?

Ответы [ 2 ]

9 голосов
/ 10 июня 2011

Это распространенная проблема, поэтому позвольте мне немного обобщить и формализовать.

Допустим, вы хотите, чтобы ваше веб-приложение поддерживало несколько языков, и у вас есть следующие требования к маршрутизации:

http://domain.com/language-code/controller-name/action-name

Другими словами, вы хотите использовать «language-code» в качестве локали и объединить предыдущее с маршрутизацией Zend-модуля по умолчанию.

Предположим, вы также хотите использовать Zend_Translate для предоставления переведенного контента в соответствии с локалью.

Вот некоторый код, который я использую и часто «экспортирую» в проект с аналогичными требованиями, я открыт для дальнейшего обсуждения.

Соответствующие элементы конфигурации:

resources.frontController.plugins.Language = Plugin_Language
resources.frontController.actionHelperPaths.Controller_Helper = APPLICATION_PATH "/controllers/helpers"


; Locale

resources.locale.default = "en_US"
resources.locale.force = false

; Translate

resources.translate.adapter = "Csv"
resources.translate.data = APPLICATION_PATH "/languages"

resources.translate.locale = "auto"
resources.translate.disableNotices = true
resources.translate.scan = directory



; Routes

resources.router.routes.module.type = Zend_Controller_Router_Route_Module
resources.router.routes.module.abstract = On    

resources.router.routes.language.type = Zend_Controller_Router_Route
resources.router.routes.language.route = ":language"
resources.router.routes.language.reqs.language = "^[a-z]{2}$"
resources.router.routes.language.defaults.language = "en"

resources.router.routes.default.type = Zend_Controller_Router_Route_Chain
resources.router.routes.default.chain = "language,module"


; View

resources.view.helperPath.View_Helper = APPLICATION_PATH "/views/helpers"

Здесь зарегистрирован язык плагинов:

class Plugin_Language extends Zend_Controller_Plugin_Abstract {

    public function routeStartup(Zend_Controller_Request_Abstract $request){

        if (substr($request->getRequestUri(), 0, -1) == $request->getBaseUrl()){

            /* Access to the Base Url (no language information) */

            /* Get current locale language (autodetected) */
            $language = Zend_Registry::get("Zend_Locale")->getLanguage();


            /* If requested language isn't available set to the default one */
            if (!Zend_Registry::get('Zend_Translate')->isAvailable($language)){

                Zend_Registry::set(
                    "Zend_Locale", 
                    new Zend_Locale("default")
                );

                $language = Zend_Registry::get("Zend_Locale")->getLanguage();

                Zend_Registry::get("Zend_Translate")->setLocale(
                    Zend_Registry::get('Zend_Locale')
                );
            }


            /* Modifiy Request Uri with Language info from current Locale */
            $request->setRequestUri($request->getRequestUri().$language."/");
            $request->setParam("language", $language);

        }
    }


    public function routeShutdown(Zend_Controller_Request_Abstract $request){

        /* Get language from request param */
        $language = $request->getParam("language");

        /* If requested language isn't available set to the default one */
        if (!Zend_Registry::get('Zend_Translate')->isAvailable($language))
            throw new Zend_Controller_Router_Exception('Translation language is not available', 404);

        /* Set the locale */ 

        Zend_Registry::set(
                "Zend_Locale",
                new Zend_Locale($language)
        );

        /* Set the traslator */ 

        Zend_Registry::get("Zend_Translate")->setLocale(
                Zend_Registry::get("Zend_Locale")
        );


    }

}

Помощник действия:

class Controller_Helper_Language extends Zend_Controller_Action_Helper_Abstract {

    /**
     * 
     * Get Current language
     * 
     * @return mixed string|null
     */
    public function getCurrent(){

        if (!Zend_Registry::isRegistered("Zend_Locale"))
            return null;

        return Zend_Registry::get("Zend_Locale")->getLanguage();

    }

    /** 
     * 
     * Get translator 
     * 
     * @return mixed Zend_Translate|null
     * 
     */
    public function getTranslator(){

        if (!Zend_Registry::isRegistered("Zend_Translate"))
            return null;

        return Zend_Registry::get("Zend_Translate");

    }

}

Помощник по URL представления (переопределяющий по умолчанию). Вы должны написать свои URL соответственно с новой маршрутизацией, которую вы используете:

    class View_Helper_Url extends Zend_View_Helper_Url {

    protected function _getCurrentLanguage(){

        return Zend_Controller_Action_HelperBroker::getStaticHelper('Language')
            ->getCurrent();

    }

    public function Url($urlOptions = array(), $name = null, $reset = true, $encode = true){

        $urlOptions = array_merge(
            array(
                "language" => $this->_getCurrentLanguage()
            ),
            $urlOptions
        );

        return parent::url($urlOptions,$name,$reset,$encode);

    }

}

Надеюсь, это поможет.

0 голосов
/ 10 июня 2011

Я бы сказал, что вы должны использовать нестандартный маршрутизатор.Это то, для чего предназначен маршрутизатор - определение параметров из URI.Теперь вы просто позволяете маршрутизатору работать без всякой причины.Потому что вы потом измените результат его работы.

Написание нестандартного маршрутизатора не так сложно, и я бы посоветовал вам сделать это.Вы можете написать что-то вроде:

  1. взорвать на /
  2. это первая часть "en", "de" или "es", если это так, установите lang = $ arr [0]
  3. работает как маршрут по умолчанию для Zend_Router

И вы можете добавить еще много опций.Также сопоставление может быть намного быстрее, потому что вы можете логически структурировать декомпозицию URI.Обычный маршрутизатор тупой - он просто сопоставляет URI с маршрутизацией и останавливается, когда совпадение найдено.

...