Hello everybody,
I have created a simple localization & routing system to allow my application to work with language subdomains.
Here's a brief description:
a class Localize is in charge of detecting the locale ( from the url, the cookies, the browser settings or the application settings)
a class Router is in charge of translating routes
a middleware Localization is in charge of redirecting the requests reaching the filtered routes without language subdomain.
Here's how my routes.php file looks like:
/**
* Detects the current locale with the following order:
*
* - Parses the requested host to find a language subdomain ( de.mydomain.com => de )
* - If previous step failed, checks if a cookie value exists for the key 'locale'
* - If previous step failed, tries to find a locale in the browser settings
* - If previous step failed, uses the fallback locale
*
* Set the application locale app()->setLocale( )
*/
Localize::detectLocale();
/**
* Without the 'localize' middleware, the route can be reached with or without language subdomain
*/
Route::get('test', function() {
return response('This route works without language subdomain');
});
/**
* Routes filtered by the 'localize' middleware can only be reached witha language subdomain
*/
Route::group([ 'middleware' => [ 'localize' ]], function() {
/**
* Router::resolve( $routeName ) returns the translated route path
*
* en.mydomain.com/welcome
* fr.mydomain.com/bienvenue
*
*/
Route::get(Router::resolve('welcome'), 'WelcomeController@index');
Route::get('hello', 'WelcomeController@index');
});
And here is the Localization ( 'localize' ) middleware:
class Localization {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
/**
* The shouldRedirect() method compares the previously detected locale to the locale guessed from the requested URL
* If they are different, then the request should be redirected
*/
if (Localize::shouldRedirect()) {
return new RedirectResponse(Router::getRedirectURL(), 302, [ 'Vary', 'Accept-Language' ]);
}
return $next($request);
}
}
The system works as intended. However, I cannot find a way to properly test it. For example, the following test fails:
/**
* It should not redirect if the locale is not missing
*
* @test
*/
public function itDoesNotRedirectIfLocaleIsNotMissing()
{
$response = $this->call('GET', 'https://de.mydomain.dev/hello');
$this->assertEquals('200', $response->getStatusCode());
}
There was 1 failure:
1) LocalizeTest::itDoesNotRedirectIfLocaleIsNotMissing
Failed asserting that 302 matches expected '200'.
/var/www/Refactoring/IndustryArena/tests/LocalizeTest.php:55
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
I have come to understand why but it isn't easy to explain. To summarize: $this->call('GET', 'https://de.mydomain.dev/hello') does not trigger the detectLocale( ) method. My guess is that the routes.php file isn't the right place to call detectLocale( ). To make my test work, this method should be triggered when a request is created in the application, and not when the application is bootstrapped.
But maybe I'm just testing this the wrong way. I think testing the routing must be a bit tricky.
Any help would be appreciated.
Thank you :)