9

私のサイトがSEOに対応できるように、ZendFrameworkでURLベースの翻訳を実装しようとしています。これは、デフォルトルートに加えて、以下のようなURLが必要であることを意味します。

zend.local/en/module
zend.local/en/controller
zend.local/en/module/controller
zend.local/en/controller/action

上記は私が今問題を抱えているものです。残り大丈夫です。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構造が同じルートに一致するため、アプリケーションがフォーマットを誤って解釈します。たとえば、次の2つのURLがlang1ルートによって照合されます。

zend.local/en/mymodule
zend.local/en/mycontroller

最初のURLでは、「mymodule」がモジュール名として使用されていますが、これは正しいです。ただし、2番目のURLでは、モジュール名として「mycontroller」が使用されていますが、これは私が望むものではありません。ここでは、「default」モジュールと「mycontroller」をコントローラーとして使用する必要があります。lang2同じことが前のルートにも当てはまります。/en/moduleそのため、URLが構造体であるか。であるかを区別する方法がわかりません/en/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ルートを機能させるために同様のことを行う必要があります(これには、コントローラーのリストを取得するためにディレクトリをスキャンすることが含まれる可能性があります)。これは貧弱な解決策のように思われるので、可能であれば、ルートのみ(またはそれほど「ハッキー」ではない単純なコード)でこれらすべてを達成したいと思います。たとえば、必要なときに毎回ルートを作成することもできます/en/controllerが、それは妥協案であり、行きたくありません。したがって、誰かがこれを解決する方法を知っているか、同じことを達成するための別のアプローチを知っているなら、私はすべての耳です!

4

1 に答える 1

1

私はここであなたの問題を再現し、次のようになりました(ただし、構成ファイルは使用していません):

ルーター

/**
 * 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

それがあなたのために働いたかどうか私に知らせてください。

于 2012-09-03T23:57:21.107 に答える