I don’t know if this is the way to go, but it works for me. First of all, wrap all your routes up in a group that takes an optional parameter named lang, something like below
$app->group('/{lang}', function() use($container) {
$this->get('/', 'HomeController:index')->setName('home');
$this->get('/signup', AuthSignUpController::class.':getSignUp')->setName('auth.signup');
$this->post('/signup', AuthSignUpController::class.':postSignUp');
$this->get('/signin', AuthSignInController::class.':getSignIn')->setName('auth.signin');
$this->post('/signin', AuthSignInController::class.':postSignIn');
});
Then in my middleware I check if the request has a parameter named lang, and I check if the value of lang is something valid.
/**
* Checks if Uri has invalid or missing language prefix, and redirects to valid route
* @package App\Middleware
*/
class UriLanguagePrefixerMiddleware
{
private $router;
private $view;
private $localization;
private $translator;
private $requestedLanguage;
public function __construct(Router $router, Twig $view, $localization, Translator $translator)
{
$this->router = $router;
$this->view = $view;
$this->localization = $localization;
$this->translator = $translator;
}
/**
* Automatically invoked during any request to the site
* @param Request | \Slim\Http\Request $request
* @param Response | \Slim\Http\Response $response
* @param $next
* @return mixed
*/
public function __invoke(Request $request, Response $response, callable $next)
{
$validLanguages = $this->localization['languages'];
// running this middleware (NON-route attached) requires settings -> determineRouteBeforeAppMiddleware = true
$route = $request->getAttribute('route');
if (null == $route) {
$routeName = 'auth.signin';
$requestedLanguage = null;
} else {
$routeName = $route->getName();
$requestedLanguage = explode('/', $route->getArgument('lang'))[0];
}
if (null == $requestedLanguage || !array_key_exists($requestedLanguage, $validLanguages)) {
$_SESSION['lang'] = key($validLanguages); // first key of language array in settings = de_DE
$requestedLanguage = $_SESSION['lang'];
return $response->withRedirect($this->router->pathFor($routeName, [
'lang' => $requestedLanguage,
]));
}
$this->view->getEnvironment()->addGlobal('lang', $requestedLanguage);
$this->translator->setLocale($requestedLanguage);
$response = $next($request, $response);
return $response;
}
}
localization comes from my settings array by the way
$app = new \Slim\App([
'settings' => [
'displayErrorDetails' => true,
'devMode' => true,
'determineRouteBeforeAppMiddleware' => true,
'localization' => [
'languages' => [
'de_DE' => 'Deutsch',
'en_US' => 'English'
],
'locales' => [
'de' => 'de_DE',
'en' => 'en_US'
],
],
]
]);