Skip to content

Commit fa1923f

Browse files
committed
Use route() helper for named routes to support translated slugs
1 parent af76cd8 commit fa1923f

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

src/LocalizedUrlGenerator.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Support\Facades\Config;
99
use Illuminate\Support\Facades\Request;
1010
use Illuminate\Support\Facades\Route;
11+
use Symfony\Component\Routing\Exception\RouteNotFoundException;
1112

1213
class LocalizedUrlGenerator
1314
{
@@ -49,6 +50,10 @@ public function generateFromRequest($locale = null, $parameters = null, $absolut
4950
$locale = $locale ?: $this->detectLocale($urlBuilder);
5051
$parameters = $this->prepareParameters($locale, $parameters ?: $this->getRouteParameters());
5152

53+
if ($url = $this->generateFromNamedRoute($locale, $parameters, $absolute)) {
54+
return $url . $urlBuilder->getQueryString();
55+
}
56+
5257
if ( ! $this->is404()) {
5358
$urlBuilder->setPath($this->replaceParameters($this->route->uri(), $parameters));
5459
}
@@ -64,6 +69,67 @@ public function generateFromRequest($locale = null, $parameters = null, $absolut
6469
return $urlBuilder->build($absolute);
6570
}
6671

72+
/**
73+
* Generate a URL for a named route.
74+
*
75+
* @param string $locale
76+
* @param array $parameters
77+
* @param bool $absolute
78+
*
79+
* @return string
80+
*/
81+
protected function generateFromNamedRoute($locale, $parameters, $absolute)
82+
{
83+
if ( ! $this->routeExists()) {
84+
return '';
85+
}
86+
87+
$name = $this->route->getName();
88+
89+
// Localized routes without a name will still have the locale prefix as a name.
90+
// Strip the prefix from the name to make sure the route has a base name set.
91+
if ($this->stripLocaleFromRouteName($name) === '') {
92+
return '';
93+
}
94+
95+
try {
96+
return route($name, $parameters, $absolute, $locale);
97+
} catch (RouteNotFoundException $e) {
98+
return '';
99+
}
100+
}
101+
102+
/**
103+
* Strip the locale from the beginning of a route name.
104+
*
105+
* @param string $name
106+
*
107+
* @return string
108+
*/
109+
protected function stripLocaleFromRouteName($name)
110+
{
111+
$parts = explode('.', $name);
112+
113+
// If there is no dot in the route name,
114+
// there is no locale in the route name.
115+
if (count($parts) === 1) {
116+
return $name;
117+
}
118+
119+
$locales = $this->getLocaleKeys();
120+
121+
// If the first part of the route name is a valid
122+
// locale, then remove it from the array.
123+
if (in_array($parts[0], $locales)) {
124+
array_shift($parts);
125+
}
126+
127+
// Rebuild the normalized route name.
128+
$name = join('.', $parts);
129+
130+
return $name;
131+
}
132+
67133
/**
68134
* Check if the current route is localized.
69135
*

src/UrlBuilder.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ public function setSlugs(array $slugs)
121121
return $this;
122122
}
123123

124+
/**
125+
* Get the query string.
126+
*
127+
* @return string
128+
*/
129+
public function getQueryString()
130+
{
131+
return $this->get('query') ? '?' . $this->get('query') : '';
132+
}
133+
124134
/**
125135
* Get the value of a URL part.
126136
*

tests/Unit/Macros/LocalizedUrlMacroTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Illuminate\Database\Eloquent\ModelNotFoundException;
1010
use Illuminate\Support\Facades\App;
1111
use Illuminate\Support\Facades\Config;
12+
use Illuminate\Support\Facades\Lang;
1213
use Illuminate\Support\Facades\Route;
1314
use Illuminate\Support\Facades\View;
1415

@@ -660,6 +661,41 @@ public function it_returns_a_url_with_query_string_for_existing_localized_named_
660661
], $response->original);
661662
}
662663

664+
/** @test */
665+
public function it_returns_a_url_with_translated_slugs_for_named_routes()
666+
{
667+
$this->setSupportedLocales(['en', 'nl']);
668+
$this->setUseLocaleMiddleware(true);
669+
$this->setAppLocale('en');
670+
671+
$this->setTranslations([
672+
'nl' => [
673+
'my-route' => 'nl-route',
674+
],
675+
'en' => [
676+
'my-route' => 'en-route',
677+
],
678+
]);
679+
680+
Route::localized(function () {
681+
Route::get(Lang::uri('route/my-route'), function () {
682+
return [
683+
'current' => Route::localizedUrl(),
684+
'en' => Route::localizedUrl('en'),
685+
'nl' => Route::localizedUrl('nl'),
686+
];
687+
})->name('route');
688+
});
689+
690+
$response = $this->call('GET', '/nl/route/nl-route');
691+
$response->assertOk();
692+
$this->assertEquals([
693+
'current' => url('/nl/route/nl-route'),
694+
'en' => url('/en/route/en-route'),
695+
'nl' => url('/nl/route/nl-route'),
696+
], $response->original);
697+
}
698+
663699
/**
664700
* Set a custom view path so Laravel will find our custom 440 error view.
665701
*

0 commit comments

Comments
 (0)