Skip to content

Commit aefc94e

Browse files
committed
Refactor locale auto detection
1 parent 093bffe commit aefc94e

File tree

6 files changed

+216
-66
lines changed

6 files changed

+216
-66
lines changed

spec/LaravelLocale/LocaleRouterSpec.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ class LocaleRouterSpec extends ObjectBehavior
1212
public function loopTest(Config $config, Router $router, $method)
1313
{
1414
$router->{$method}('home', 'HomeController@index')->shouldBeCalled();
15+
$router->{$method}('ja/home', 'HomeController@index')->shouldBeCalled();
1516
$router->{$method}('en/home', 'HomeController@index')->shouldBeCalled();
1617
$router->{$method}('fr/home', 'HomeController@index')->shouldBeCalled();
1718

1819
$router->{$method}('home', ['as' => 'home', 'uses' => 'HomeController@index'])
1920
->shouldBeCalled();
2021

22+
$router->{$method}('ja/home', ['as' => 'ja.home', 'uses' => 'HomeController@index'])
23+
->shouldBeCalled();
24+
2125
$router->{$method}('en/home', ['as' => 'en.home', 'uses' => 'HomeController@index'])
2226
->shouldBeCalled();
2327

src/LaravelLocale/LocaleFacade.php

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/LaravelLocale/LocaleRouter.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,6 @@ protected function generateRoutes($method, $uri, $action)
107107
$default = $this->config->get('app.fallback_locale');
108108

109109
foreach ($availables as $locale) {
110-
if ($locale == $default) {
111-
$this->router->{$method}($uri, $action);
112-
continue;
113-
}
114-
115110
$localedUri = $locale . '/' . $uri;
116111

117112
if ( ! isset($action['as'])) {
@@ -125,5 +120,7 @@ protected function generateRoutes($method, $uri, $action)
125120

126121
$this->router->{$method}($localedUri, $localedAction);
127122
}
123+
124+
$this->router->{$method}($uri, $action);
128125
}
129126
}

src/LaravelLocale/LocaleUrlGenerator.php

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,36 +102,23 @@ public function change($locale)
102102
* @return string
103103
*/
104104
public function urlFor($locale)
105-
{
106-
if ($locale == $this->config->get('app.fallback_locale')) {
107-
return $this->replaceLocaleString();
108-
}
109-
110-
return $this->replaceLocaleString($locale);
111-
}
112-
113-
/**
114-
* Replace locale string from uri.
115-
*
116-
* @param string $uri
117-
* @param string $target
118-
* @param string $replace
119-
* @return string
120-
*/
121-
protected function replaceLocaleString($replace = '/')
122105
{
123106
$uri = $this->getFullUri();
124107
$firstSegment = $this->request->segment(1);
125108

126109
if ( ! in_array($firstSegment, $this->config->get('locale.available_locales'))) {
110+
if ($firstSegment == $this->config->get('app.fallback_locale')) {
111+
return $uri;
112+
}
113+
127114
$root = $this->request->root();
128115

129-
return str_replace($root, "{$root}/{$replace}", $this->getFullUri());
116+
return str_replace($root, "{$root}/{$locale}", $uri);
130117
}
131118

132-
$replace = $replace != '/' ? "/{$replace}/" : '/';
119+
$replace = $locale == $this->config->get('app.fallback_locale') ? '' : "/{$locale}";
133120

134-
return preg_replace('/\/('.$firstSegment.')(\/)?/', $replace, $uri, 1);
121+
return preg_replace('/\/('.$firstSegment.')/', $replace, $uri, 1);
135122
}
136123

137124
/**

src/LaravelLocale/Manager.php

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
<?php
2+
3+
namespace KiaKing\LaravelLocale;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Contracts\Config\Repository as Config;
7+
8+
class Manager
9+
{
10+
/**
11+
* The config implementation.
12+
*
13+
* @var \Illuminate\Contracts\Config\Repository
14+
*/
15+
protected $config;
16+
17+
/**
18+
* The request implementation.
19+
*
20+
* @var \Illuminate\Http\Request
21+
*/
22+
protected $request;
23+
24+
/**
25+
* Create a new Locale Middleware instance.
26+
*
27+
* @param \Illuminate\Contracts\Config\Repository $config
28+
* @param \Illuminate\Http\Request $request
29+
*/
30+
public function __construct(Config $config, Request $request)
31+
{
32+
$this->config = $config;
33+
$this->request = $request;
34+
}
35+
36+
/**
37+
* Get default locale for application.
38+
*
39+
* @return string
40+
*/
41+
public function getDefaultLocale()
42+
{
43+
return $this->config->get('app.fallback_locale');
44+
}
45+
46+
/**
47+
* Get list of available locales.
48+
*
49+
* @return array
50+
*/
51+
public function getAvailableLocales()
52+
{
53+
return $this->config->get('locale.available_locales');
54+
}
55+
56+
/**
57+
* Get locale for uri.
58+
*
59+
* @return string
60+
*/
61+
public function getUriLocale()
62+
{
63+
$segment = $this->request->segment(1);
64+
65+
if ($this->isValidLocale($segment)) {
66+
return $segment;
67+
}
68+
69+
return $this->getDefaultLocale();
70+
}
71+
72+
/**
73+
* Get user's locale.
74+
*
75+
* @return string
76+
*/
77+
public function getUserLocale()
78+
{
79+
if ($this->getCookieLocale()) {
80+
return $this->getCookieLocale();
81+
}
82+
83+
if ($this->isValidLocale($this->getBrowserLocale())) {
84+
$this->getBrowserLocale();
85+
}
86+
87+
return $this->getDefaultLocale();
88+
}
89+
90+
/**
91+
* Get browser locale.
92+
*
93+
* @return string
94+
*/
95+
public function getBrowserLocale()
96+
{
97+
return substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
98+
}
99+
100+
/**
101+
* Get locale stored at cookie.
102+
*
103+
* @return mixed
104+
*/
105+
public function getCookieLocale()
106+
{
107+
return $this->request->cookie('locale');
108+
}
109+
110+
/**
111+
* Set application locale.
112+
*
113+
* @param string $locale
114+
* @return void
115+
*/
116+
public function setLocale($locale)
117+
{
118+
$this->config->set('app.locale', $locale);
119+
}
120+
121+
/**
122+
* Set locale to cookie.
123+
*
124+
* @param mixed $response
125+
* @param string $locale
126+
* @return \Illuminate\Http\Response
127+
*/
128+
public function setCookieLocale($response, $locale)
129+
{
130+
return $response->withCookie('locale', $locale, 525600);
131+
}
132+
133+
/**
134+
* Check if the given locale is available.
135+
*
136+
* @param string $locale
137+
* @return boolean
138+
*/
139+
public function isValidLocale($locale)
140+
{
141+
return in_array($locale, $this->getAvailableLocales());
142+
}
143+
144+
/**
145+
* Get switch request locale.
146+
*
147+
* @return mixed
148+
*/
149+
public function getSwitchRequestLocale()
150+
{
151+
$locale = $this->localeSwitchRequest();
152+
153+
return $this->isValidLocale($locale) ? $locale : $this->getUserLocale();
154+
}
155+
156+
/**
157+
* Get locale switch request.
158+
*
159+
* @return mixed
160+
*/
161+
public function localeSwitchRequest()
162+
{
163+
return $this->request->switch_locale_to;
164+
}
165+
}

src/LaravelLocale/Middleware/Locale.php

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
use Closure;
66
use Illuminate\Contracts\Config\Repository as Config;
77
use Illuminate\Contracts\Routing\ResponseFactory as Response;
8-
use Illuminate\Contracts\Routing\Middleware;
8+
use KiaKing\LaravelLocale\Manager;
99
use KiaKing\LaravelLocale\LocaleUrlGenerator as Url;
1010

11-
class Locale implements Middleware
11+
class Locale
1212
{
1313
/**
14-
* The config implementation.
14+
* The locale manager implementation.
1515
*
16-
* @var \Illuminate\Contracts\Config\Repository
16+
* @var \KiaKing\LaravelLocale\Manager
1717
*/
18-
protected $config;
18+
protected $manager;
1919

2020
/**
2121
* The response implementation.
@@ -34,14 +34,14 @@ class Locale implements Middleware
3434
/**
3535
* Create a new Locale Middleware instance.
3636
*
37-
* @param \Illuminate\Contracts\Config\Repository $config
37+
* @param \KiaKing\LaravelLocale\Manager $manager
3838
* @param \Illuminate\Contracts\Routing\ResponseFactory $response
3939
* @param \KiaKing\LaravelLocale\LocaleUrlGenerator $url
4040
* @return void
4141
*/
42-
public function __construct(Config $config, Response $response, Url $url)
42+
public function __construct(Manager $manager, Response $response, Url $url)
4343
{
44-
$this->config = $config;
44+
$this->manager = $manager;
4545
$this->response = $response;
4646
$this->url = $url;
4747
}
@@ -51,38 +51,50 @@ public function __construct(Config $config, Response $response, Url $url)
5151
*
5252
* @param \Illuminate\Http\Request $request
5353
* @param \Closure $next
54+
* @param bool $autoDetect
5455
* @return mixed
5556
*/
56-
public function handle($request, Closure $next)
57+
public function handle($request, Closure $next, $autoDetect = false)
5758
{
58-
$locale = $request->segment(1);
59-
$default = $this->config->get('app.fallback_locale');
60-
61-
if (in_array($locale, $this->config->get('locale.available_locales'))) {
62-
$this->config->set('app.locale', $locale);
59+
// If user requested to change locale, redirect them to proper page.
60+
if ($this->manager->localeSwitchRequest()) {
61+
return $this->redirect($this->manager->getSwitchrequestLocale(), $autoDetect);
6362
}
6463

65-
if ($request->switch_locale_to) {
66-
return $this->redirect($request->switch_locale_to);
64+
// When auto detection is on and if user's locale and URI locale
65+
// doesn't matches redirect them.
66+
if ($autoDetect && ($this->manager->getUriLocale() != $this->manager->getUserLocale())) {
67+
return $this->redirect($this->manager->getUserLocale(), $autoDetect);
6768
}
6869

69-
$userLocale = $request->cookie('locale') ? $request->cookie('locale') : substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
70+
// If the first segment of URI is same as default locale redirect them.
71+
if ($request->segment(1) == $this->manager->getDefaultLocale()) {
72+
$locale = $autoDetect ? $this->manager->getUserLocale() : $this->manager->getDefaultLocale();
7073

71-
if ($userLocale != $this->config->get('app.locale')) {
72-
return $this->redirect($userLocale);
74+
return $this->redirect($locale, $autoDetect);
7375
}
7476

75-
if ($locale == $default) {
76-
return $this->response->redirectTo($this->url->urlFor($default));
77-
}
77+
$this->manager->setLocale($this->manager->getUriLocale());
7878

7979
return $next($request);
8080
}
8181

82-
protected function redirect($locale)
82+
/**
83+
* Redirect to specific locale page and set cookie to remember their
84+
* setting.
85+
*
86+
* @param string $locale
87+
* @param bool $autoDetect
88+
* @return Response
89+
*/
90+
protected function redirect($locale, $autoDetect = false)
8391
{
84-
return $this->response
85-
->redirectTo($this->url->urlFor($locale))
86-
->withCookie('locale', $locale, 525600);
92+
$response = $this->response->redirectTo($this->url->urlFor($locale));
93+
94+
if ($autoDetect) {
95+
$response = $this->manager->setCookieLocale($response, $locale);
96+
}
97+
98+
return $response;
8799
}
88100
}

0 commit comments

Comments
 (0)