Skip to content

Commit f1321b7

Browse files
authored
Add support for custom slugs and domains (#12)
1 parent bd128b9 commit f1321b7

File tree

4 files changed

+177
-6
lines changed

4 files changed

+177
-6
lines changed

README.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,25 @@ You will now find a `localizer.php` file in the `config` folder.
8080
Add any locales you wish to support to your published `config/localizer.php` file:
8181

8282
```php
83-
'supported-locales' => ['en', 'nl', 'fr'];
83+
'supported-locales' => ['en', 'nl'];
84+
```
85+
86+
You can also use one or more custom slugs for a locale:
87+
88+
```php
89+
'supported-locales' => [
90+
'en' => 'english-slug',
91+
'nl' => ['dutch-slug', 'nederlandse-slug'],
92+
];
93+
```
94+
95+
Or you can use one or more custom domains for a locale:
96+
97+
```php
98+
'supported-locales' => [
99+
'en' => 'english-domain.test',
100+
'nl' => ['dutch-domain.test', 'nederlands-domain.test'],
101+
];
84102
```
85103

86104
### Configure Detectors
@@ -96,9 +114,6 @@ By default, the middleware will use the following detectors to check for a suppo
96114
7. The browser
97115
8. The app's default locale
98116

99-
You can set a custom attribute or "action" on a route group.
100-
This is especially useful in combination with the [codezero/laravel-localized-routes](https://github.com/codezero-be/laravel-localized-routes) package.
101-
102117
If you set an omitted locale, no additional detectors will run after the `OmittedLocaleDetector`.
103118
This makes sense, because the locale will always be determined by the URL in this scenario.
104119

src/Detectors/UrlDetector.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,44 @@ class UrlDetector implements Detector
1414
*/
1515
public function detect()
1616
{
17+
$locales = Config::get('localizer.supported-locales');
1718
$position = Config::get('localizer.url-segment');
19+
$slug = Request::segment($position);
1820

19-
return Request::segment($position);
21+
// If supported locales is a simple array like ['en', 'nl']
22+
// just return the slug and let Localizer check if it is supported.
23+
if (array_key_exists(0, $locales)) {
24+
return $slug;
25+
}
26+
27+
// Find the locale that belongs to the custom domain or slug.
28+
$domain = Request::getHttpHost();
29+
$locales = $this->flipLocalesArray($locales);
30+
$locale = $locales[$domain] ?? $locales[$slug] ?? null;
31+
32+
return $locale;
33+
}
34+
35+
/**
36+
* Flip the locales array so the custom domain or slug
37+
* become the key and the locale becomes te value.
38+
*
39+
* @param array $locales
40+
*
41+
* @return array
42+
*/
43+
protected function flipLocalesArray($locales)
44+
{
45+
$flipped = [];
46+
47+
foreach ($locales as $locale => $values) {
48+
$values = is_array($values) ? $values : [$values];
49+
50+
foreach ($values as $value) {
51+
$flipped[$value] = $locale;
52+
}
53+
}
54+
55+
return $flipped;
2056
}
2157
}

src/Localizer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class Localizer
3636
*/
3737
public function __construct($locales, $detectors, $stores = [])
3838
{
39-
$this->locales = $locales;
39+
$this->setSupportedLocales($locales);
4040
$this->detectors = $detectors;
4141
$this->stores = $stores;
4242
}
@@ -84,6 +84,10 @@ public function store($locale)
8484
*/
8585
public function setSupportedLocales(array $locales)
8686
{
87+
if ( ! array_key_exists(0, $locales)) {
88+
$locales = array_keys($locales);
89+
}
90+
8791
$this->locales = $locales;
8892

8993
return $this;

tests/Feature/SetLocaleTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,122 @@ public function you_can_configure_which_segment_to_use_as_locale()
9797
$this->assertEquals('nl', $response->original);
9898
}
9999

100+
/** @test */
101+
public function it_looks_for_custom_slugs()
102+
{
103+
$this->setSupportedLocales([
104+
'en' => 'english',
105+
'nl' => 'dutch',
106+
'fr' => 'french',
107+
]);
108+
$this->setAppLocale('en');
109+
110+
Route::get('dutch/some/route', function () {
111+
return App::getLocale();
112+
})->middleware(['web', SetLocale::class]);
113+
114+
$response = $this->get('dutch/some/route');
115+
116+
$response->assertSessionHas($this->sessionKey, 'nl');
117+
$response->assertCookie($this->cookieName, 'nl');
118+
$this->assertEquals('nl', $response->original);
119+
}
120+
121+
/** @test */
122+
public function you_can_use_multiple_slugs_for_a_locale()
123+
{
124+
$this->setSupportedLocales([
125+
'en' => 'english',
126+
'nl' => ['dutch', 'nederlands'],
127+
'fr' => 'french',
128+
]);
129+
$this->setAppLocale('en');
130+
131+
Route::get('dutch/some/route', function () {
132+
return App::getLocale();
133+
})->middleware(['web', SetLocale::class]);
134+
135+
Route::get('nederlands/some/route', function () {
136+
return App::getLocale();
137+
})->middleware(['web', SetLocale::class]);
138+
139+
$response = $this->get('dutch/some/route');
140+
141+
$response->assertSessionHas($this->sessionKey, 'nl');
142+
$response->assertCookie($this->cookieName, 'nl');
143+
$this->assertEquals('nl', $response->original);
144+
145+
$response = $this->get('nederlands/some/route');
146+
147+
$response->assertSessionHas($this->sessionKey, 'nl');
148+
$response->assertCookie($this->cookieName, 'nl');
149+
$this->assertEquals('nl', $response->original);
150+
}
151+
152+
/** @test */
153+
public function it_looks_for_custom_domains()
154+
{
155+
$this->setSupportedLocales([
156+
'en' => 'english.test',
157+
'nl' => 'dutch.test',
158+
'fr' => 'french.test',
159+
]);
160+
$this->setAppLocale('en');
161+
162+
Route::group([
163+
'domain' => 'dutch.test',
164+
], function () {
165+
Route::get('some/route', function () {
166+
return App::getLocale();
167+
})->middleware(['web', SetLocale::class]);
168+
});
169+
170+
$response = $this->get('http://dutch.test/some/route');
171+
172+
$response->assertSessionHas($this->sessionKey, 'nl');
173+
$response->assertCookie($this->cookieName, 'nl');
174+
$this->assertEquals('nl', $response->original);
175+
}
176+
177+
/** @test */
178+
public function you_can_use_multiple_domains_for_a_locale()
179+
{
180+
$this->setSupportedLocales([
181+
'en' => 'english.test',
182+
'nl' => ['dutch.test', 'nederlands.test'],
183+
'fr' => 'french.test',
184+
]);
185+
$this->setAppLocale('en');
186+
187+
Route::group([
188+
'domain' => 'dutch.test',
189+
], function () {
190+
Route::get('some/route', function () {
191+
return App::getLocale();
192+
})->middleware(['web', SetLocale::class]);
193+
});
194+
195+
Route::group([
196+
'domain' => 'nederlands.test',
197+
], function () {
198+
Route::get('some/route', function () {
199+
return App::getLocale();
200+
})->middleware(['web', SetLocale::class]);
201+
});
202+
203+
$response = $this->get('http://dutch.test/some/route');
204+
205+
$response->assertSessionHas($this->sessionKey, 'nl');
206+
$response->assertCookie($this->cookieName, 'nl');
207+
$this->assertEquals('nl', $response->original);
208+
209+
$response = $this->get('http://nederlands.test/some/route');
210+
211+
$response->assertSessionHas($this->sessionKey, 'nl');
212+
$response->assertCookie($this->cookieName, 'nl');
213+
$this->assertEquals('nl', $response->original);
214+
}
215+
100216
/** @test */
101217
public function it_checks_for_a_configured_omitted_locale()
102218
{

0 commit comments

Comments
 (0)