Ответ 1
rchavik из IRC предложил эту ссылку: CakePHP Переключение на основе URL-адресов для интернационализации и локализации i18n и l10n
В общем, кажется, что решение Helper::url
может быть решением.
Какой самый чистый способ добавить префикс для каждого URL-адреса в CakePHP, например параметр языка?
http://example.com/en/controller/action
http://example.com/ru/admin/controller/action
Он должен работать с "настоящими" префиксами, такими как admin
, и в идеале голый URL /controller/action
можно перенаправить на /DEFAULT-LANGUAGE/controller/action
.
Теперь он работает в ретро-приложении для меня, но это был своего рода хак, и мне нужно включить параметр языка вручную в большинстве ссылок, что не очень хорошо.
Итак, вопрос двоякий:
Router::connect('/:controller/:action/*', ...)
должен неявно включать префикс.$this->params['lang']
или где-то аналогично, чтобы быть оцененным в AppController::beforeFilter()
.Router::url()
для автоматического включения префикса в URL-адрес, если он явно не указан?
Router::url(array('controller' => 'foo', 'action' => 'bar'))
должен возвращать /en/foo/bar
Controller::redirect()
, Form::create()
или даже Router::url()
напрямую необходимо иметь одинаковое поведение, переопределение каждой отдельной функции на самом деле не является опцией. Html::image()
, например, должен содержать URL без префикса.Следующие методы, похоже, вызывают Router::url
.
Controller::redirect
Controller::flash
Dispatcher::__extractParams
через Object::requestAction
Helper::url
JsHelper::load_
JsHelper::redirect_
View::uuid
, но только для генерации хешейИз них кажется, что методы Controller и Helper необходимо переопределить, я мог бы жить без JsHelper
. Моя идея состояла бы в том, чтобы написать общую функцию в AppController
или, возможно, только в bootstrap.php
для обработки вставки параметров. Переопределенные методы Controller и Helper будут использовать эту функцию, как если бы я захотел вручную вызвать Router::url
. Достаточно ли этого?
rchavik из IRC предложил эту ссылку: CakePHP Переключение на основе URL-адресов для интернационализации и локализации i18n и l10n
В общем, кажется, что решение Helper::url
может быть решением.
Это, по сути, весь код, который я реализовал для решения этой проблемы в конце (по крайней мере, я думаю, что все; -)):
/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}'));
Это позволяет использовать URL по умолчанию, например /controller/action
, для использования языка по умолчанию (JPN в моем случае) и для URL-адресов, например /eng/controller/action
, для использования альтернативного языка. Эту логику можно легко изменить в функции router_url_language()
.
Для этого мне также нужно определить два маршрута для каждого маршрута, один из которых содержит параметр /:language/
, а один без него. По крайней мере, я не мог понять, как это сделать по-другому.
Более простым способом может быть сохранение выбранного языка в файле cookie, а затем не нужно переписывать все URL-адреса. Вы также можете автоматически определить язык пользовательского браузера.
Однако, поисковые системы вряд ли будут захватывать различные языки, и вы также потеряете язык, если кто-то попытается поделиться ссылкой.
Но любите полное решение, которое вы разместили, очень всеобъемлющее, спасибо.: -)