自2012年以来,this post似乎是关于如何在CakePHP中执行本地化路由的最权威资源(下面复制的代码)。
效果很好,但有一个例外:它不会重定向缺少语言前缀的请求。例如,http://example.com将显示与http://example.com/eng相同的内容(如果英语是默认语言)。同样,如果它不是主页:http://example.com/foo/bar/ => http://example.com/eng/foo/bar。在评论中提到了这个问题,但没有决定性的解决方案,这就是我正在寻找的。 p>
代码。
// Step 1: app/Config/routes.php
Router::connect('/:language/:controller/:action/*',
array(),
array('language' => 'eng|fra'));
Router::connect('/:language/:controller',
array('action' => 'index'),
array('language' => 'eng|fra'));
Router::connect('/:language',
array('controller' => 'welcome', 'action' => 'index'),
array('language' => 'eng|fra'));
//Step 2: app/Config/core.php
Configure::write('Config.language', 'eng');
//Step 3: create app/View/Helper/MyHtmlHelper.php
App::uses('HtmlHelper', 'View/Helper');
class MyHtmlHelper extends HtmlHelper {
public function url($url = null, $full = false) {
if(!isset($url['language']) && isset($this->params['language'])) {
$url['language'] = $this->params['language'];
}
return parent::url($url, $full);
}
}
//Step 4: app/Controller/AppController.php
class AppController extends Controller {
public $components = array('Cookie','Session');
//set an alias for the newly created helper: Html<->MyHtml
public $helpers = array('Html' => array('className' => 'MyHtml'));
public function beforeFilter() {
$this->_setLanguage();
}
private function _setLanguage() {
//if the cookie was previously set, and Config.language has not been set
//write the Config.language with the value from the Cookie
if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
$this->Session->write('Config.language', $this->Cookie->read('lang'));
}
//if the user clicked the language URL
else if ( isset($this->params['language']) &&
($this->params['language'] != $this->Session->read('Config.language'))
) {
//then update the value in Session and the one in Cookie
$this->Session->write('Config.language', $this->params['language']);
$this->Cookie->write('lang', $this->params['language'], false, '20 days');
}
}
//override redirect
public function redirect( $url, $status = NULL, $exit = true ) {
if (!isset($url['language']) && $this->Session->check('Config.language')) {
$url['language'] = $this->Session->read('Config.language');
}
parent::redirect($url,$status,$exit);
}
}
//add the links to the languages:
//Step 5: app/View/...
echo $this->Html->link('English', array('language'=>'eng'));
echo $this->Html->link('Français', array('language'=>'fra'));
更新1
我尝试了用户221931的建议,但它似乎没有用。以下是我添加到我的路线中的内容:
/* Add default language param */
Router::redirect('/:controller/:action/*',
array('language' => 'fra'),
array('persist' => false) );
Router::redirect('/:controller/',
array('language' => 'fra'),
array('persist' => false) );
Router::redirect('/',
array('controller'=>'pages', 'action'=>'display', 'language' => 'fra', 'home'),
array('persist' => false) );
似乎没有效果。以下网址未重定向:http:example.com,http://example.com/controller/,http://example.com/controller/action/
更新2 根据要求,这是我的完整的路线文件:
<?php
/**
* Routes configuration
*
* In this file, you set up routes to your controllers and their actions.
* Routes are very important mechanism that allows you to freely connect
* different URLs to chosen controllers and their actions (functions).
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package app.Config
* @since CakePHP(tm) v 0.2.9
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#http://book.cakephp.org/2.0/en/views/json-and-xml-views.html
Router::parseExtensions('json');
/**
* Here, we are connecting '/' (base path) to controller called 'Pages',
* its action called 'display', and we pass a param to select the view file
* to use (in this case, /app/View/Pages/home.ctp)...
*/
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
/**
* ...and connect the rest of 'Pages' controller's URLs.
*/
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
/**
* LOCALIZED URLs
* See: http://colorblindprogramming.com/multiple-languages-in-a-cakephp-2-application-in-5-steps
*/
Router::connect('/:language/:controller/:action/*',
array(),
array('language' => 'eng|fra'));
Router::connect('/:language/:controller',
array('action' => 'index'),
array('language' => 'eng|fra'));
Router::connect('/:language',
array('controller' => 'pages', 'action' => 'display', 'home'),
array('language' => 'eng|fra'));
# prevent routing conflicts with plugins...
# http://www.omaroid.com/cakephp-locale-language-routing/
// make an array of loaded plugins
$loaded = CakePlugin::loaded();
array_walk($loaded, function(&$item,$key){
$item = Inflector::underscore($item);
});
$loaded = implode('|', $loaded);
Router::connect('/:language/:plugin/:controller/:action/*',
array(),
array('language' => 'eng|fra','plugin' => "($loaded)"));
/* HIDE /index */
//Router::connect('/:controller/', array('action'=>'index') );
Router::connect('/:language/:controller/', array('action'=>'index') );
/**
* Load all plugin routes. See the CakePlugin documentation on
* how to customize the loading of plugin routes.
*/
CakePlugin::routes();
/**
* Load the CakePHP default routes. Only remove this if you do not want to use
* the built-in default routes.
*/
require CAKE . 'Config' . DS . 'routes.php';
答案 0 :(得分:1)
您添加了非常具体的语言路由(如果网址路径的第一部分是eng
或fra
)但是没有删除默认路由(Router::connect('/:controller/:action/*'
),所以如果这些找不到两个单词/:controller/:action/*
将匹配的更通用的路线。
您可以执行以下三项操作中的任何一项:
/:controller/:action/*
和/:controller/*
无法路由,并且没有人能够在没有语言的情况下形成将访问内容的网址。routes
的硬编码eng
,即/users
- &gt; /eng/users
,/posts/
- &gt; /eng/posts
等)。这可能看起来很多工作,但是虽然模式匹配对于开发来说是可以接受的,但硬编码可以显着提高路由的速度,因此您可能需要在未来的某些方面采用这种方式。它的另一个优点是,您可以添加persist
规则,使浏览器记住重定向,而不再点击服务器。AppController
中添加代码,检查路径中是否包含语言,如果没有尝试从浏览器设置中猜测用户语言,则重定向到最合适的网址或默认值。< / LI>
醇>
1号是最简单,最干净,最快的,但如果您的控制器不需要在前面使用语言,则可能不合适。
2号码不会让您选择使用哪种语言重定向,因为它将被硬编码。根据应用程序的不同,它可能完全没问题。
从UX的角度来看,Number 3是最优雅的解决方案,但是每个页面加载会产生一些轻微的开销(通过检查语言)。
答案 1 :(得分:1)
从AppController.php可以很简单:
const DEFAULT_LANGUAGE = 'eng';
public function beforeFilter() {
parent::beforeFilter();
if (empty($this->params['language'])) {
$this->redirect(array('language' => self::DEFAULT_LANGUAGE));
}
}