Skip to content

Commit d6a6cbc

Browse files
committed
Refactor Route::localized() macro
1 parent 8209af3 commit d6a6cbc

File tree

2 files changed

+121
-78
lines changed

2 files changed

+121
-78
lines changed

src/LocalizedRoutesRegistrar.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
namespace CodeZero\LocalizedRoutes;
4+
5+
use Illuminate\Support\Facades\App;
6+
use Illuminate\Support\Facades\Config;
7+
use Illuminate\Support\Facades\Route;
8+
use Illuminate\Support\Str;
9+
10+
class LocalizedRoutesRegistrar
11+
{
12+
/**
13+
* Register routes for every configured locale.
14+
*
15+
* @param Closure $closure
16+
* @param array $options
17+
*
18+
* @return void
19+
*/
20+
public function register($closure, $options = [])
21+
{
22+
$locales = $options['supported_locales'] ?? Config::get('localized-routes.supported_locales', []);
23+
$omitPrefix = $options['omitted_locale'] ?? Config::get('localized-routes.omitted_locale');
24+
$localeRouteAction = Config::get('localized-routes.route_action');
25+
26+
if (count($locales) === 0) {
27+
return;
28+
}
29+
30+
$firstValue = array_values($locales)[0];
31+
$usingDomains = Str::contains($firstValue, '.');
32+
$usingCustomSlugs = ! $usingDomains && ! is_numeric(key($locales));
33+
34+
// Move the omitted locale to the end of the array to avoid
35+
// root parameter placeholders catching hard-coded slugs.
36+
$locales = $this->moveOmittedLocaleToEnd($locales, $omitPrefix, $usingDomains, $usingCustomSlugs);
37+
38+
// Remember the current locale, so we can
39+
// change it during route registration.
40+
$currentLocale = App::getLocale();
41+
42+
foreach ($locales as $locale => $domainOrSlug) {
43+
// If the locale key is numeric, we have a simple array of locales.
44+
// In this case, the locale is the same as the slug.
45+
if ( ! $usingDomains && ! $usingCustomSlugs) {
46+
$locale = $domainOrSlug;
47+
}
48+
49+
// Prepend the locale to the route names and set
50+
// a custom route action, so the middleware can
51+
// find it to set the correct app locale.
52+
$attributes = [
53+
'as' => "{$locale}.",
54+
$localeRouteAction => $locale,
55+
];
56+
57+
// Add a custom domain to the route group
58+
// when custom domains are configured.
59+
if ($usingDomains) {
60+
$attributes['domain'] = $domainOrSlug;
61+
}
62+
63+
// Add a URL prefix to the route group, unless
64+
// the locale is configured to be omitted.
65+
if ( ! $usingDomains && $locale !== $omitPrefix) {
66+
$attributes['prefix'] = $domainOrSlug;
67+
}
68+
69+
// Temporarily change the active locale, so any
70+
// translations made in the routes closure are
71+
// automatically in the correct language.
72+
App::setLocale($locale);
73+
74+
// Register the route group.
75+
Route::group($attributes, $closure);
76+
}
77+
78+
// Restore the original locale.
79+
App::setLocale($currentLocale);
80+
}
81+
82+
/**
83+
* Move the omitted locale to the end of the locales array.
84+
*
85+
* @param array $locales
86+
* @param string|null $omitPrefix
87+
* @param bool $usingDomains
88+
* @param bool $usingCustomSlugs
89+
*
90+
* @return array
91+
*/
92+
protected function moveOmittedLocaleToEnd($locales, $omitPrefix, $usingDomains, $usingCustomSlugs)
93+
{
94+
if ( ! $omitPrefix || $usingDomains) {
95+
return $locales;
96+
}
97+
98+
// When using custom slugs, the locales are the array keys.
99+
// Remove it from the array and add it back on to the end.
100+
if ($usingCustomSlugs) {
101+
$omitSlug = $locales[$omitPrefix];
102+
unset($locales[$omitPrefix]);
103+
$locales[$omitPrefix] = $omitSlug;
104+
105+
return $locales;
106+
}
107+
108+
// When not using custom slugs, the array keys are numeric.
109+
// Filter out the omitted locale and then add it back to the end.
110+
$locales = array_filter($locales, function ($locale) use ($omitPrefix) {
111+
return $locale !== $omitPrefix;
112+
});
113+
114+
$locales[] = $omitPrefix;
115+
116+
return $locales;
117+
}
118+
}

src/Macros/Route/LocalizedMacro.php

Lines changed: 3 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
namespace CodeZero\LocalizedRoutes\Macros\Route;
44

5+
use CodeZero\LocalizedRoutes\LocalizedRoutesRegistrar;
56
use Illuminate\Support\Facades\App;
6-
use Illuminate\Support\Facades\Config;
77
use Illuminate\Support\Facades\Route;
8-
use Illuminate\Support\Str;
98

109
class LocalizedMacro
1110
{
@@ -16,82 +15,8 @@ class LocalizedMacro
1615
*/
1716
public static function register()
1817
{
19-
Route::macro('localized', function ($callback, $options = []) {
20-
// Remember the current locale so we can
21-
// change it during route registration.
22-
$currentLocale = App::getLocale();
23-
24-
$locales = $options['supported_locales'] ?? Config::get('localized-routes.supported_locales', []);
25-
$omitPrefix = $options['omitted_locale'] ?? Config::get('localized-routes.omitted_locale');
26-
27-
if (count($locales) === 0) {
28-
return;
29-
}
30-
31-
$firstValue = array_values($locales)[0];
32-
$usingDomains = Str::contains($firstValue, '.');
33-
$usingCustomSlugs = ! $usingDomains && ! is_numeric(key($locales));
34-
35-
// Move the omitted locale to the end of the array
36-
// to avoid root placeholders catching existing slugs.
37-
// https://github.com/codezero-be/laravel-localized-routes/issues/28
38-
if ($omitPrefix && ! $usingDomains) {
39-
if ($usingCustomSlugs) {
40-
$omitSlug = $locales[$omitPrefix];
41-
unset($locales[$omitPrefix]);
42-
$locales[$omitPrefix] = $omitSlug;
43-
} else {
44-
$locales = array_filter($locales, function ($locale) use ($omitPrefix) {
45-
return $locale !== $omitPrefix;
46-
});
47-
$locales[] = $omitPrefix;
48-
}
49-
}
50-
51-
foreach ($locales as $locale => $domainOrSlug) {
52-
// Allow supported locales to be a
53-
// simple array of locales or an
54-
// array of ['locale' => 'domain']
55-
if ( ! $usingDomains && ! $usingCustomSlugs) {
56-
$locale = $domainOrSlug;
57-
$domainOrSlug = null;
58-
}
59-
60-
// Change the current locale so we can
61-
// use it in the callback, for example
62-
// to register translated route URI's.
63-
App::setLocale($locale);
64-
65-
// Prepend the locale to the route name
66-
// and set a custom attribute so the middleware
67-
// can find it to set the correct app locale.
68-
$localeRouteAction = Config::get('localized-routes.route_action');
69-
$attributes = [
70-
'as' => "{$locale}.",
71-
$localeRouteAction => $locale
72-
];
73-
74-
// Add a custom domain route group
75-
// if a domain is configured.
76-
if ($usingDomains) {
77-
$attributes['domain'] = $domainOrSlug;
78-
}
79-
80-
// Map the locale string to a prefix.
81-
$prefix = $usingCustomSlugs ? $domainOrSlug : $locale;
82-
83-
// Prefix the URL unless the locale
84-
// is configured to be omitted.
85-
if ( ! $usingDomains && $locale !== $omitPrefix) {
86-
$attributes['prefix'] = $prefix;
87-
}
88-
89-
// Execute the callback inside route group
90-
Route::group($attributes, $callback);
91-
}
92-
93-
// Restore the original locale.
94-
App::setLocale($currentLocale);
18+
Route::macro('localized', function ($closure, $options = []) {
19+
App::make(LocalizedRoutesRegistrar::class)->register($closure, $options);
9520
});
9621
}
9722
}

0 commit comments

Comments
 (0)