Hello to everyone,
I’m new here; I’m from Geneva (speaking french, so sorry for my approximate english!), and I’ve started to learn Slim3 for few months. I would like to have your advices to start a multilingual website with that kind of structure :
I saw a tutorial from Brian Nesbitt (http://nesbot.com/2012/6/26/multilingual-site-using-slim) that could help managing this if there is a route with no specific language, but it was done with Slim2 and I really would like to have translated URI, too… So I really wonder if I need something else than the routes themselves to call my controllers. (and maybe the group). I could maybe just detect the language of the browser if the route is not informed (like “http://127.0.0.1/contact”, because “contact” could be english or french…) and redirect to the good route ?
What do you think about it ?
Thank you in advance for your answer.
// Home index, the 'root'
$app->get('/', \App\Action\HomeIndexAction::class)->setName('root');
// languages only
$app->get('/en', \App\Action\EnglishIndexAction::class);
$app->get('/fr', \App\Action\FrenchIndexAction::class);
// ------------------------------------------------------------------------
// All routes without the language argument
// Only required for the redirect
// ------------------------------------------------------------------------
$app->get('/about', \App\Action\AboutEnRedirectAction::class);
$app->get('/a-propos', \App\Action\AboutFrRedirectAction::class);
$app->get('/contact', \App\Action\ContactRedirectAction::class);
$app->get('/login', \App\Action\LoginEnRedirectAction::class);
$app->get('/se-connecter', \App\Action\LoginFrRedirectAction::class);
// ------------------------------------------------------------------------
// The real page routes
// ------------------------------------------------------------------------
$app->get('/en/about', \App\Action\AboutIndexEnAction::class)->setName('about-en');
$app->get('/fr/a-propos', \App\Action\AboutIndexFrAction::class)->setName('about-fr');
$app->get('/en/contact', \App\Action\ContactIndexEnAction::class)->setName('contact-en');
$app->get('/fr/contact', \App\Action\ContactIndexFrAction::class)->setName('contact-fr');
// add more...
For all routes with a redirect use the accept-language attribute from the $request object:
$acceptLanguage = $request->getAttribute('accept-language');
// customize this route name
$routeName = sprintf('contact-%s', $acceptLanguage);
$url = $this->router->pathFor($routeName);
return $response->withRedirect($url);
Thank you for your answer.
I just don’t understand where you would like to put your last few lines of code. Inside the Controller, just before render the view ?
And how can I manage my menu lang in a general template ? Idealy, I would need a fonction to change the current URL with the chosen language… or am I wrong ?
I don’t know your exact routing definitions. My examples are very generic. Put the code with the redirect logic only in the controller (action) methods you have to perform a redirect for example: in /fr/en/about/a-propos and so on… You don’t have to put this logic in the routes like /en/about or /fr/a-propos because that’s the correct page and a redirect is unnecessary there, right?
And how can I manage my menu lang in a general template ?
Do you use Twig? You could pass the translated strings to your general template and Twig will render it. Another approach is to translate the text in Twig with a translation extension. If you use native PHP templates then you just call a helper translation function like __('my text') within the template to translate the text. But without more details about your requirement it’s not easy to give a “good” answer here.
Yes I use twig. And I could load my lang file inside the controller. Everything is ok for that.
I understood what you did and your generic exemples are good. I just wonder if there is a way to avoid this multiplication of redirections… Because, in your exemple, for the same page, there are 4 page controllers (with the page “about” : AboutEnRedirectAction, AboutFrRedirectAction, AboutIndexEnAction, AboutIndexFrAction) while I’ve got only one twig file… (for exemple : “about.twig”) where I just need to load the good language depending the URL…
Is there maybe a way to pass a parameter (the lang) to the controller directly inside “$app->get” ?
I would imagine it a bit like this (with a third parameter) for the page controller “about” (of course, this doesn’t work) : $app->get('/about', PagesController::class . ':about', 'en'); $app->get('/a-propos', PagesController::class . ':about', 'fr'); $app->get('en/about', PagesController::class . ':about', 'en'); $app->get('fr/a-propos', PagesController::class . ':about', 'fr');
I also tried this, without success : $app->get('/fr', call_user_func_array(PagesController::class . ':home', 'fr'));
I have to name routes with lang for twig (to use it with « path for ») :
->setName(‘about-en’);
->setName(‘about-fr’);
So I need 1 pagecontroller per lang…
And redirection for the rest. So you did right !