Skip to content

Commit

Permalink
add support for custom prefixes for localized routes (codezero-be#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanerkay committed Jan 10, 2023
1 parent 6e77ffd commit f03028f
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 6 deletions.
10 changes: 10 additions & 0 deletions config/localized-routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,14 @@
*/
'use_localizer' => false,

/**
* Map application locale to a custom route prefix.
*
* 'custom_prefixes' => [
* 'en' => 'english',
* 'nl' => 'dutch',
* ]
*/
'custom_prefixes' => [],

];
4 changes: 2 additions & 2 deletions src/Controller/FallbackController.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function __invoke()
}
}

return $this->NotFoundResponse();
return $this->notFoundResponse();
}

/**
Expand All @@ -54,7 +54,7 @@ protected function findRouteByUrl($url)
*
* @return \Illuminate\Http\Response
*/
protected function NotFoundResponse()
protected function notFoundResponse()
{
$view = Config::get('localized-routes.404_view');

Expand Down
5 changes: 4 additions & 1 deletion src/LocalizedUrlGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,13 @@ public function generateFromRequest($locale = null, $parameters = null, $absolut
$urlBuilder->setPath($this->replaceParameters($this->route->uri(), $slugs));
}

// Map the locale string to a prefix.
$prefix = data_get(Config::get('localized-routes.custom_prefixes'), $locale, $locale);

// If custom domains are not used and it is not a registered,
// non localized route, update the locale slug in the path.
if (!$this->hasCustomDomains() && ($this->is404() || $this->isLocalized())) {
$urlBuilder->setSlugs($this->updateLocaleInSlugs($urlBuilder->getSlugs(), $locale));
$urlBuilder->setSlugs($this->updateLocaleInSlugs($urlBuilder->getSlugs(), $prefix));
}

if ($domain = $this->getCustomDomain($locale)) {
Expand Down
7 changes: 5 additions & 2 deletions src/Macros/LocalizedRoutesMacro.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,14 @@ public static function register()
// to register translated route URI's.
App::setLocale($locale);

// Map the locale string to a prefix.
$prefix = data_get(Config::get('localized-routes.custom_prefixes'), $locale, $locale);

// Prepend the locale to the route name
// and set a custom attribute so the middleware
// can find it to set the correct app locale.
$attributes = [
'as' => "{$locale}.",
'as' => "{$prefix}.",
'localized-routes-locale' => $locale
];

Expand All @@ -71,7 +74,7 @@ public static function register()
// Prefix the URL unless the locale
// is configured to be omitted.
if ($domain === null && $locale !== $omitPrefix) {
$attributes['prefix'] = $locale;
$attributes['prefix'] = $prefix;
}

if ($setMiddleware) {
Expand Down
5 changes: 4 additions & 1 deletion src/UrlGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,16 @@ public function route($name, $parameters = [], $absolute = true, $locale = null)
// as a prefix for the route name.
$locale = $locale ?: $currentLocale;

// Map the locale string to a prefix.
$prefix = data_get(Config::get('localized-routes.custom_prefixes'), $locale, $locale);

// Normalize the route name by removing any locale prefix.
// We will prepend the applicable locale manually.
$baseName = $this->stripLocaleFromRouteName($name);

// If the route has a name (not just the locale prefix)
// add the requested locale prefix.
$newName = $baseName ? "{$locale}.{$baseName}" : '';
$newName = $baseName ? "{$prefix}.{$baseName}" : '';

// If the new localized name does not exist, but the unprefixed route name does,
// someone might be calling "route($name, [], true, $locale)" on a non localized route.
Expand Down
12 changes: 12 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ protected function setUseLocalizer($value)
Config::set('localized-routes.use_localizer', $value);
}

/**
* Set the custom prefixes config option.
*
* @param array $prefixes
*
* @return void
*/
protected function setCustomPrefixes($prefixes)
{
Config::set('localized-routes.custom_prefixes', $prefixes);
}

/**
* Fake that we created a routes.php file in 'resources/lang/'
* for each language with the given translations.
Expand Down
22 changes: 22 additions & 0 deletions tests/Unit/Middleware/SetLocaleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,26 @@ public function it_passes_the_supported_locales_to_localizer_in_the_correct_form

$localizer->shouldHaveReceived('setSupportedLocales')->with(['en', 'nl']);
}

/** @test */
public function it_sets_the_right_locale_with_custom_prefixes()
{
$this->setSupportedLocales(['en', 'nl']);
$this->setCustomPrefixes(['en' => 'english', 'nl' => 'dutch']);
$this->setUseLocaleMiddleware(true);

Route::localized(function () {
Route::get('/', function () {
return App::getLocale();
});
});

$response = $this->call('GET', '/english');
$response->assertOk();
$this->assertEquals('en', $response->original);

$response = $this->call('GET', '/dutch');
$response->assertOk();
$this->assertEquals('nl', $response->original);
}
}
29 changes: 29 additions & 0 deletions tests/Unit/RedirectToLocalizedTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,33 @@ public function it_throws_404_and_does_not_redirect_if_no_localized_route_is_reg
$this->setAppLocale('en');
$this->get('missing')->assertNotFound();
}

/** @test */
public function it_redirects_to_the_localized_url_with_custom_prefixes()
{
$this->withoutExceptionHandling();
$this->setSupportedLocales(['en', 'nl']);
$this->setCustomPrefixes(['en' => 'english', 'nl' => 'dutch']);
$this->setUseLocaleMiddleware(false);
$this->setRedirectToLocalizedUrls(true);

Route::localized(function () {
Route::get('/', function () {});
Route::get('about', function () {});
});

Route::fallback(\CodeZero\LocalizedRoutes\Controller\FallbackController::class);

$this->setAppLocale('en');
$this->get('/')->assertRedirect('english');
$this->get('english')->assertOk();
$this->get('about')->assertRedirect('english/about');
$this->get('english/about')->assertOk();

$this->setAppLocale('nl');
$this->get('/')->assertRedirect('dutch');
$this->get('dutch')->assertOk();
$this->get('about')->assertRedirect('dutch/about');
$this->get('dutch/about')->assertOk();
}
}
34 changes: 34 additions & 0 deletions tests/Unit/RouteModelBindingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,38 @@ public function it_loads_a_route_with_a_custom_localized_route_key_based_on_the_
$this->get('en/test/en-slug')->assertOk();
$this->get('en/test/nl-slug')->assertNotFound();
}

/** @test */
public function it_loads_a_route_with_a_localized_route_key_with_custom_prefixes()
{
$this->setSupportedLocales(['en', 'nl']);
$this->setCustomPrefixes(['en' => 'english', 'nl' => 'dutch']);
$this->setUseLocaleMiddleware(true);

$model = (new Model([
'slug' => [
'en' => 'en-slug',
'nl' => 'nl-slug',
],
]))->setKeyName('slug');

App::instance(Model::class, $model);

Route::middleware(['web'])->get('test/{model}', function (Model $model) {});

Route::localized(function () {
Route::middleware(['web'])->get('test/{model}', function (Model $model) {});
});

$this->setAppLocale('nl');

$this->get('test/nl-slug')->assertOk();
$this->get('test/en-slug')->assertNotFound();

$this->get('dutch/test/nl-slug')->assertOk();
$this->get('dutch/test/en-slug')->assertNotFound();

$this->get('english/test/en-slug')->assertOk();
$this->get('english/test/nl-slug')->assertNotFound();
}
}
17 changes: 17 additions & 0 deletions tests/Unit/UrlGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,23 @@ public function it_allows_routes_to_be_cached()
$this->get('en/route')->assertSuccessful();
}

/** @test */
public function it_maps_locales_with_custom_prefixes()
{
$this->setSupportedLocales(['en', 'nl', 'fr']);

// Set custom prefixes for all locales except "fr"
$this->setCustomPrefixes(['en' => 'english', 'nl' => 'dutch']);

$this->registerRoute('english/route', 'english.route');
$this->registerRoute('dutch/route', 'dutch.route');
$this->registerRoute('fr/route', 'fr.route');

$this->assertEquals(url('english/route'), route('english.route'));
$this->assertEquals(url('dutch/route'), route('dutch.route'));
$this->assertEquals(url('fr/route'), route('fr.route'));
}

/**
* Cache registered routes.
*
Expand Down

0 comments on commit f03028f

Please sign in to comment.