Cakephp localization routes - cakephp

My localization files (.po) work if I change the default language, but I can't make the routes working, here's what I've got atm:
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/login/*', array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout/*', array('controller' => 'users', 'action' => 'logout'));
Router::connect('/register/*', array('controller' => 'users', 'action' => 'register'));
Router::connect('/:lang/:controller/:action/*', array('lang' => 'en'), array('lang' => 'en|fr'));
But when I try : domain.com/fr/login, the cake is looking for the "fr" controller.
I am using this function in the AppController beforeFilter to switch between languages:
function setLanguage() {
if(!isset($this->params['lang']))
{
$this->params['lang'] = 'en';
}
$lang = $this->params['lang'];
App::import('Core', 'i18n');
$I18n =& I18n::getInstance();
$I18n->l10n->get($lang);
foreach (Configure::read('Config.languages') as $lang => $locale)
{
if($lang == $this->params['lang'])
{
$this->params['locale'] = $locale['locale'];
}
}
}
Cheers,
Nicolas.

You do not have a login controller. So your bottom route does not match and Cake then tries the default by looking for an fr controller.
Routes don't interact as you expect them to:
/login - would match your second route
/fr/users/login - would match your last route.
/fr/login - does NOT intelligently "merge" the two routes. You need to explicitly make such a route.

Related

How to route subcategories and pages in categories?

My subcategories and pages in categories have similar structure. For example:
site.com/cat/page
site.com/cat/subcat
How can I route them? URLs consist only of strings, no IDs and any numbers.
Pretty straightforward, your routes.php could look like:
$routes->connect(
'/cat/:page',
['controller' => 'Pages', 'action' => 'view'],
['page' => '\s+', 'pass' => ['page']]
);
$routes->connect(
'/cat/:subcat/:page',
['controller' => 'Pages', 'action' => 'subcatView'],
['subcat' => '\s+', 'page' => '\s+', 'pass' => ['subcat', 'page']]
);
Next, in your PagesController.php (actually you can use any other your controller/action, just substitute your names in routes above):
public function view($page) {
//i.e. if url is /cat/about then $page === 'about'
}
public function subcatView($subcat, $page) {
// i.e. if url is /cat/subcat/some_page then $subcat === 'subcat' & $page === 'some_page'
}
I highly recommend to refer cakephp3 documentation, routes section, it's clear enough to help you implement any magic.

Cakephp Site Root with username conflict with controllers

I got this code working.
when i go to domain.com/ it will route to home->index(). when i type in domain.com/username.. it will route to users->view(username)
file: config/routes.php
$controllerList = App::objects('Controller');
foreach($controllerList as $controller)
{
$controllerName = str_replace('Controller', '', $controller);
if($controllerName != "App" & $controllerName != "Pages")
{
Router::connect('/' . $controllerName . '/:action/*', array('controller' => $controllerName));
$firstLetterLower = strtolower(substr($controllerName,0,1));
$lowerCaseName = $firstLetterLower . substr($controllerName,1);
Router::connect('/' . $lowerCaseName . '/:action/*', array('controller' => $lowerCaseName));
}
}
Router::connect('/:username', array('controller' => 'users', 'action' => 'views'), array('pass' => array('username')));
Router::connect('/', array('controller' => 'home', 'action' => 'index'));
the problem is that i cannot route my controllers domain.com/controller without putting the action..
This will work: domain.com/blog/index, domain.com/forum/index, domain.com/users/login
This wont work: domain.com/blog it will be treated as username
Exclude the controller names from being matched in the username route. You should have a list of them to prevent people from registering with these names at all.
Put you code like this. this will not treat blog as username
Router::connect('/', array('controller' => 'home', 'action' => 'index'));
Router::connect('/blog', array('controller' => 'blog', 'action' => 'index'));
Router::connect('/:username', array('controller' => 'users', 'action' => 'views'), array('pass' => array('username')));
Thanks..!

CakePHP setflash page refresh doesn't keep language in url

I have a multi language website, but when I don't do a redirect with a setFlash, it deletes the language from the url. Example: if the contactform doesn't validate, it just does a setFlash without the redirect, so that user input data is not lost. But it does refresh the page and deletes the language part from my url. This does not happen when I do a redirect after my setFlash, because I give the language param with the redirect. Work flow:
I start on the page website.com/eng/contact (notice the language part). I fill in the contact form and fill in all required inputs. It redirects me to website.com/eng/contact/send. That's great and what I want. But when I don't give an valid email adres for example, it display an error (great), but the url has changed to website.com/forms/contact (notice the missing language part, and it doesn't use my routes). What am I doing wrong? My code:
Formscontroller.php
public function contact() {
if ($this->request->is('post')) {
$this->Form->set($this->request->data);
if ($this->Form->validates()) {
if($this->Form->save($this->request->data)){
$this->redirect(array('controller' => 'forms', 'action' => 'contact_success', 'language' => $this->Session->read('Config.language')));
} else {
$this->Session->setFlash(__('Er ging iets mis met het versturen van uw contactformulier, probeer het opnieuw.'), 'flash_error');
}
} else {
$this->Session->setFlash(__('Niet alle verplichte velden zijn ingevuld.'), 'flash_error');
}
}
}
routes.php
Router::connect('/:language/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/:language/contact', array('controller' => 'forms', 'action' => 'contact'), array('language' => 'ned|eng'));
Router::connect('/:language/contact/verzonden', array('controller' => 'forms', 'action' => 'contact_success'), array('language' => 'ned'));
Router::connect('/:language/contact/send', array('controller' => 'forms', 'action' => 'contact_success'), array('language' => 'eng'));
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/:language', array('controller' => 'pages', 'action' => 'display', 'home'), array('language' => 'eng|ned'));
Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{3}'));
CakePlugin::routes();
require CAKE . 'Config' . DS . 'routes.php';
I was looking in the wrong direction for my problem. As ndm points out in his comment on my question, it had to do with the action of my form, it didn't have the language part in it. So thanks to ndm for pointing me in the right direction!

Login takes away the slug from my URL

I'm working Cake 2.1.3, and the routes.php file, everything worked fine except the login management, for example I want my url be as follows:
http://mysite.com/companyx/users/login
where companyx is the slug, however when you run that url in the browser is as follows:
http://mysite.com/users/login
In this file routes.php I have defined as follows:
Router::connect(
'/:slug/users/login', // E.g. /companyx/users/login
array('controller' => 'users', 'action' => 'login'), array(
// order matters
'pass' => array('slug')
)
);
With other controllers I have no problems such as:
Router::connect(
'/:slug/users', // E.g. /companyx/users
array('controller' => 'users', 'action' => 'index'), array(
// order matters
'pass' => array('slug')
)
);
Best Regards ;)
CakePHP has a default login action defined in the AuthComponent. (line 171)
/**
* A URL (defined as a string or array) to the controller action that handles
* logins. Defaults to `/users/login`
*
* #var mixed
*/
public $loginAction = array(
'controller' => 'users',
'action' => 'login',
'plugin' => null
);
You can override this action with the beforeFilter in your own UsersController.
thanks for you answer. I solved this case this way:
public function beforeFilter() {
parent::beforeFilter();
if (!$this->request->is('post')) {
$this->Auth->loginAction = 'this is:slug/users/login/';
}
}
Where "this is slug", should be the slug.
Best Regards.

CakePHP - how to translate current URL after changing language and reloading Routing table

I'm using different routing tables for every language, and I have wrote action which change language and redirects to the same page but in target language (and target url).
The main problem is that my action is way too complicated - how can I make it simple?
It should change language and redirect to new url (in target language).
In short: We had random valid cake url in one language and we had to translate it to adequate url in another language.
My routing table:
if( 'en' == Configure::read('Config.language') ) {
Router::connect('/help', array('controller' => 'pages', 'action' => 'display', 'help') );
} else {
Router::connect('/pomoc', array('controller' => 'pages', 'action' => 'display', 'help') );
}
Action changing language:
function lang($lang) {
// getting previous url table
$url = $this->referer();
$url = Router::parse($url);
// changing language
if( in_array($lang, Configure::read('Languages.valid') ) ) {
$this->Session->write('Language', $lang);
Configure::write('Config.language', $lang);
}
// saving base params
$requestInfo = array(Router::getParams(), Router::getPaths());
// reload routing table
Router::reload();
include(CONFIGS.'routes.php');
// restore base params
Router::setRequestInfo($requestInfo);
// fix for 'pass' params
if(!empty($url['pass']) && is_array($url['pass'])) {
$url = array_merge($url, $url['pass']);
unset($url['pass']);
}
$this->redirect($url);
}
About 'pass' key in url table:
/pages/display/help
after Router::parse(), parameter is extracted:
pass => array(
0 => 'help'
)
and later return value from Router::url() look like that:
/pages/display/pass:Array
so I have to fix it by merging 'pass' value with whole array and removing key
I have my routes.php like this
Configure::write('Config.language', $_SESSION['lang']);
Router::connect(__('/help',true), array('controller' => 'pages', 'action' => 'display', 'help') );
so I use the __() to translate the url. It seaches the translation in the po files. And in your lang() function, after changing the Session to the current lang, all you need to do is:
$this->redirect(__('/help'));
Hope this helps
I know it is too late to answer that, but for those who experience the similar needs:
In routes.php p1 identifies the static page (same for all languages), could be any string that uniquely identifies the page.
Router::connect('/:language/p1/:translation', array(
'controller' => 'pages',
'action' => 'display',
'help',
'options' => array('language' => '[a-zA-Z]{2}')
) );
In your view
$this->Html->link('Click me', array(
'language' => Configure::read('Config.language'),
'controller' => 'pages',
'action' => 'display',
'help',
'translation' => __('help') // could be any string in fact
));
will generate link to /en/p1/help in English, else to /xx/p1/pomoc.
Injection of language parameter into every link could be done in AppHelper::url() instead of providing it in every link occurence.
If you want to redirect in controller:
$this->redirect(array(
'language' => Configure::read('Config.language'),
'controller' => 'pages',
'action' => 'display',
'help',
'translation' => __('help')
));

Resources