我正在尝试在 Zend Framework 中实现基于 URL 的翻译,以便我的网站对 SEO 友好。这意味着除了默认路由之外,我还需要如下所示的 URL。
zend.local/en/module
zend.local/en/controller
zend.local/en/module/controller
zend.local/en/controller/action
以上是我目前遇到的问题;其余应该没问题。我添加了一个 Controller 插件来获取 lang
参数,这样我就可以在 preDispatch
方法中设置语言环境和翻译对象。这是我的一些路线(存储在 .ini 文件中):
; Language + module
; Language + controller
resources.router.routes.lang1.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.lang1.route = "(^[a-zA-Z]{2})/(\w+$)"
resources.router.routes.lang1.defaults.controller = index
resources.router.routes.lang1.defaults.action = index
resources.router.routes.lang1.map.1 = "lang"
resources.router.routes.lang1.map.2 = "module"
; Language + module + controller
; Language + controller + action
resources.router.routes.lang2.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.lang2.route = "(^[a-zA-Z]{2})/(\w+)/(\w+$)"
resources.router.routes.lang2.defaults.module = default
resources.router.routes.lang2.defaults.action = index
resources.router.routes.lang2.map.1 = "lang"
resources.router.routes.lang2.map.2 = "controller"
resources.router.routes.lang2.map.3 = "action"
如注释所示,多个 URL 结构将匹配同一路由,这使我的应用程序无法正确解释格式。例如,以下两个 URL 将被 lang1
路由匹配:
zend.local/en/mymodule
zend.local/en/mycontroller
在第一个 URL 中,“mymodule”用作模块名称,这是正确的。但是,在第二个 URL 中,“mycontroller”用作模块名称,这不是我想要的。在这里我希望它使用“默认”模块和“mycontroller”作为 Controller 。这同样适用于之前的 lang2
路由。所以我不知道如何区分 URL 是结构 /en/module
还是 /en/controller
。
为了解决这个问题,我在我的 Controller 插件中尝试了以下代码。
// Get module names as array
$dirs = Zend_Controller_Front::getInstance()->getControllerDirectory();
$modules = array_keys($dirs);
// Module variable contains a module that does not exist
if (!in_array($request->getModuleName(), $modules)) {
// Try to use it as controller name instead
$request->setControllerName($request->getModuleName());
$request->setModuleName('default');
}
这在我测试的场景中工作正常,但是我必须做一些类似的事情来使 lang2
路由工作(这可能涉及扫描目录以获取 Controller 列表)。这似乎是一个糟糕的解决方案,所以如果可能的话,我很乐意仅使用路由(或不那么“hacky”的简单代码)来完成所有这些。例如,我可以也可以为每次我想要的/en/controller
制定路线,但这是一种我不愿接受的妥协。所以,如果有人知道如何解决这个问题,或者知道另一种方法来完成同样的事情,我会洗耳恭听!
最佳答案
我在这里重现了您的问题并得出了以下结果(虽然没有使用配置文件):
路由器
/**
* Initializes the router
* @return Zend_Controller_Router_Interface
*/
protected function _initRouter() {
$locale = Zend_Registry::get('Zend_Locale');
$routeLang = new Zend_Controller_Router_Route(
':lang',
array(
'lang' => $locale->getLanguage()
),
array('lang' => '[a-z]{2}_?([a-z]{2})?')
);
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
// Instantiate default module route
$routeDefault = new Zend_Controller_Router_Route_Module(
array(),
$frontController->getDispatcher(),
$frontController->getRequest()
);
// Chain it with language route
$routeLangDefault = $routeLang->chain($routeDefault);
// Add both language route chained with default route and
// plain language route
$router->addRoute('default', $routeLangDefault);
// Register plugin to handle language changes
$frontController->registerPlugin(new Plugin_Language());
return $router;
}
插件
/**
* Language controller plugin
*/
class Plugin_Language extends Zend_Controller_Plugin_Abstract
{
/**
* @var array The available languages
*/
private $languages = array('en', 'pt');
/**
* Check the URI before starting the route process
* @param Zend_Controller_Request_Abstract $request
*/
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$translate = Zend_Registry::get('Zend_Translate');
$lang = $translate->getLocale();
// Extracts the URI (part of the URL after the project public folder)
$uri = str_replace($request->getBaseUrl() . '/', '', $request->getRequestUri());
$langParam = substr($uri, 0, 3);
// Fix: Checks if the language was specified (if not, set it on the URI)
if((isset($langParam[2]) && $langParam[2] !== '/') || !in_array(substr($langParam, 0, 2), $this->languages)) { {
$request->setRequestUri($request->getBaseUrl() . '/' . $lang . "/" . $uri);
$request->setParam('lang', $lang);
}
}
}
基本上,在模块默认路由中有应用语言设置的路由链。作为修复,我们确保 URI 将包含用户遗漏的语言。
你需要调整它,因为我正在使用 Zend_Registry::get('Zend_Locale')
和 Zend_Registry::get('Zend_Translate')
.将其更改为您应用中的实际键。
至于 lang 路由:[a-z]{2}_?([a-z]{2})?
它将允许像我这样的语言:pt_BR
如果它对你有用,请告诉我。
关于php - Zend Framework 基于 URL 的翻译路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12179566/