【问题标题】:properly use of languages in zend framework在 zend 框架中正确使用语言
【发布时间】:2011-06-10 06:46:19
【问题描述】:

我有一个带有两个模块(管理员和公共)的 Zend 应用程序,对于公共,我有以下插件来解析我的友好 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 将“en”设置为控制器,将“user”设置为操作。如何正确设置网址中的语言?

【问题讨论】:

    标签: zend-framework uri routes


    【解决方案1】:

    这是一个常见的问题,所以让我概括和形式化一点。

    假设您希望您的网络应用支持多种语言,并且您有以下路由要求:

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

    换句话说,您想使用“语言代码”作为语言环境,并将前一个与默认的 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 帮助器(覆盖默认值)。您必须使用您正在使用的新路由相应地编写您的网址:

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

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      我会说你应该使用自定义路由器。这就是路由器的用途 - 从 URI 确定参数。现在你只是让路由器无缘无故地工作。因为你然后改变了它的工作结果。

      编写自定义路由器并不难,我建议你应该这样做。你可以写这样的东西:

      1. 由 / 分解
      2. 是第一部分“en”、“de”或“es”,如果是,则设置 lang = $arr[0]
      3. 作为 Zend_Router 的默认路由工作

      您还可以添加更多选项。匹配也可能更快,因为您可以在逻辑上构建 URI 分解。普通路由器是愚蠢的 - 它只匹配 URI 以路由正则表达式并在找到匹配时停止。

      【讨论】:

        猜你喜欢
        • 2012-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 2013-08-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多