full_base_url - request is cakephp
Agregar un prefijo a cada URL en CakePHP (3)
¿Cuál es la forma más limpia de agregar un prefijo a cada URL en CakePHP, como un parámetro de idioma?
http://example.com/en/controller/action
http://example.com/ru/admin/controller/action
Tiene que funcionar con prefijos "reales" como admin
, e idealmente la URL /controller/action
podría ser redirigida a /DEFAULT-LANGUAGE/controller/action
.
Ahora estoy trabajando en una aplicación retroadaptada, pero fue un truco, y necesito incluir el parámetro de idioma a mano en la mayoría de los enlaces, lo cual no es bueno.
Entonces la pregunta es doble:
- ¿Cuál es la mejor manera de estructurar Rutas, por lo que el parámetro de idioma se incluye implícitamente por defecto sin tener que especificarse para cada Ruta recién definida?
-
Router::connect(''/:controller/:action/*'', ...)
debe incluir implícitamente el prefijo. - El parámetro debe estar disponible en
$this->params[''lang'']
o en algún lugar similar para ser evaluado enAppController::beforeFilter()
.
-
- ¿Cómo obtener
Router::url()
para incluir automáticamente el prefijo en la URL, si no se especifica explícitamente?-
Router::url(array(''controller'' => ''foo'', ''action'' => ''bar''))
debería devolver/en/foo/bar
- Dado que
Controller::redirect()
,Form::create()
o inclusoRouter::url()
directamente necesitan tener el mismo comportamiento, anular todas y cada una de las funciones no es realmente una opción.Html::image()
por ejemplo, debería producir una URL sin prefijo.
-
Los siguientes métodos parecen llamar a Router::url
.
-
Controller::redirect
-
Controller::flash
-
Dispatcher::__extractParams
través deObject::requestAction
-
Helper::url
-
JsHelper::load_
-
JsHelper::redirect_
-
View::uuid
, pero solo para una generación hash
De esos parece que los métodos Controller y Helper deberían ser anulados, podría vivir sin el JsHelper
. Mi idea sería escribir una función general en AppController
o tal vez solo en bootstrap.php
para manejar la inserción de parámetros. Los métodos reemplazados de Controller y Helper usarían esta función, como lo haría si quisiera llamar manualmente a Router::url
. ¿Esto sería suficiente?
Esto es esencialmente todo el código que implementé para resolver este problema al final (al menos creo que eso es todo ;-)):
/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}''));
Esto permite que las URL predeterminadas como /controller/action
utilicen el idioma predeterminado (JPN en mi caso) y las URL como /eng/controller/action
para usar un idioma alternativo. Esta lógica se puede cambiar bastante fácilmente en la función router_url_language()
.
Para que esto funcione, también necesito definir dos rutas para cada ruta, una que contenga el /:language/
parámetro y otra sin. Al menos no pude entender cómo hacerlo de otra manera.
Una manera más fácil podría ser almacenar el idioma elegido en una cookie y luego no tener que volver a escribir todas las URL. También es posible que detecte el idioma del navegador del usuario automáticamente.
Sin embargo , es poco probable que los motores de búsqueda capten los distintos idiomas y también perderías el idioma si alguien intentara compartir el enlace.
Pero ama la solución completa que publicaste, muy completa, gracias. :-)
rchavik de IRC sugirió este enlace: cambio de idioma basado en URL CakePHP para la internacionalización y localización i18n y l10n
En general, parece que anular Helper::url
podría ser la solución.