Ajouter un préfixe à chaque URL dans CakePHP

Quelle est la façon la plus propre d'ajouter un préfixe à chaque URL dans CakePHP, comme un paramètre de langue?

http://example.com/en/controller/action
http://example.com/ru/admin/controller/action

il doit fonctionner avec des préfixes" réels " comme admin, et idéalement L'URL nue /controller/action pourrait être redirigé vers /DEFAULT-LANGUAGE/controller/action.

cela fonctionne dans une application rétro-ajustée pour moi maintenant, mais c'était une sorte de hack, et j'ai besoin d'inclure le paramètre de langue à la main dans la plupart des liens, ce qui n'est pas bon.

Donc la question est double:

  • Quelle est la meilleure façon de structurer les Routes, de sorte que le paramètre de langue est implicitement inclus par défaut sans avoir à être spécifié pour chaque Route nouvellement définie?
    • Router::connect('/:controller/:action/*', ...) devrait inclure implicitement le préfixe.
    • le paramètre doit être disponible en $this->params['lang'] ou dans un endroit semblable à être évalués dans AppController::beforeFilter().
  • Comment obtenir Router::url() pour inclure automatiquement le préfixe dans L'URL, sinon explicitement spécifié?
    • Router::url(array('controller' => 'foo', 'action' => 'bar')) devrait revenir /en/foo/bar
    • Depuis Controller::redirect(),Form::create() ou encore Router::url() directement besoin d'avoir le même comportement, en remplaçant chaque fonction n'est pas vraiment une option. Html::image() par exemple devrait produire une URL sans préfixe.

Les méthodes suivantes semblent appeler Router::url.

  • Controller::redirect
  • Controller::flash
  • Dispatcher::__extractParams par Object::requestAction
  • Helper::url
  • JsHelper::load_
  • JsHelper::redirect_
  • View::uuid, mais seulement pour un hachage génération

de ceux-là, il semble que les méthodes de Controller et Helper devraient être supplantées, je pourrais vivre sans le JsHelper. Mon idée serait d'écrire une fonction générale dans AppController ou peut-être juste dans bootstrap.php pour gérer l'insertion du paramètre. Les méthodes overridden Controller et Helper utiliseraient cette fonction, comme je le ferais si je voulais appeler manuellement Router::url. Serait-ce suffisant?

20
demandé sur deceze 2009-11-25 06:17:11

3 réponses

rchavik de L'IRC a suggéré ce lien:commutation de langue basée sur L'URL CakePHP pour l'internationalisation et la localisation de i18n et l10n

En général, il semble que primordial Helper::url pourrait être la solution.

5
répondu Joe Phillips 2009-11-25 04:34:17

C'est essentiellement tout le code que j'ai mis en œuvre pour résoudre ce problème à la fin (au moins je crois que c'est tout ;-)):

/ config / bootstrap.php

define('DEFAULT_LANGUAGE', 'jpn');

if (!function_exists('router_url_language')) {
    function router_url_language($url) {
        if ($lang = Configure::read('Config.language')) {
            if (is_array($url)) {
                if (!isset($url['language'])) {
                    $url['language'] = $lang;
                }
                if ($url['language'] == DEFAULT_LANGUAGE) {
                    unset($url['language']);
                }
            } else if ($url == '/' && $lang !== DEFAULT_LANGUAGE) {
                $url.= $lang;
            }
        }

        return $url;
    }
}

/ config / core.php

Configure::write('Config.language', 'jpn');

/app_helper.php

class AppHelper extends Helper {

    public function url($url = null, $full = false) {
        return parent::url(router_url_language($url), $full);
    }

}

/app_controller.php

class AppController extends Controller {

    public function beforeFilter() {
        if (isset($this->params['language'])) {
            Configure::write('Config.language', $this->params['language']);
        }
    }

    public function redirect($url, $status = null, $exit = true) {
        parent::redirect(router_url_language($url), $status, $exit);
    }

    public function flash($message, $url, $pause = 1) {
        parent::flash($message, router_url_language($url), $pause);
    }

}

/ config / routes.php

Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/:language/', array('controller' => 'pages', 'action' => 'display', 'home'), array('language' => '[a-z]{3}'));
Router::connect('/:language/pages/*', array('controller' => 'pages', 'action' => 'display'), array('language' => '[a-z]{3}'));
Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{3}'));

cela permet des URLs par défaut comme /controller/action utilisation de la langue par défaut (JPN dans mon cas), et les Url de la forme /eng/controller/action pour utiliser un langage alternatif. Cette logique peut être changé assez facilement dans le router_url_language() fonction.

pour que cela fonctionne, je dois aussi définir deux routes pour chaque route, l'une contenant le /:language/ paramètre et un sans. Au moins, je ne pouvais pas comprendre comment le faire d'une autre manière.

14
répondu deceze 2010-02-18 06:46:41

un moyen plus simple pourrait être de stocker la langue choisie dans un cookie et de ne pas avoir à réécrire toutes les URLs. Vous pouvez également détecter le langage du navigateur de l'utilisateur automatiquement.

cependant, les moteurs de recherche seraient peu susceptibles de ramasser les différentes langues et vous perdriez également la langue si quelqu'un essayait de partager le lien.

mais j'aime la solution complète que vous avez posté, très complet, merci. : -)

0
répondu Simon East 2012-09-28 05:01:10