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 dansAppController::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 encoreRouter::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
parObject::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?
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.
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.
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. : -)