Zend框架中正确使用语言
问题描述:
我有两个模块(管理和公共)和Zend公司申请公开我有以下的插件来分析我的友好,网址:Zend框架中正确使用语言
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 “作为控制器和”用户“作为动作。我怎样才能在URL中正确设置语言?
答
这是一个常见问题,所以让我进行一般化和形式化。
比方说,你希望你的web应用程序支持多国语言,你有以下路由要求:
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");
}
}
视图网址助手(覆盖默认的)。你必须相应地使用你正在使用的新路由编写你的网址:
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);
}
}
希望得到这个帮助。
答
我想说你应该使用自定义路由器。这是路由器的用途 - 从URI确定参数。现在你只需让路由器无故地工作。因为你然后改变它的工作结果。
编写自定义路由器并不困难,我建议你应该这样做。你可以在里面写类似:
- 通过/
- 爆炸是第一部分 “恩”, “德” 或 “ES”,如果是这样设置LANG = $改编[0]
- 工作作为默认Zend_Router的路线
而且您可以添加更多选项。也可以更快地匹配,因为您可以逻辑地构造URI分解。正常路由器是愚蠢的 - 它只是匹配URI来路由正则表达式,并在找到匹配时停止。