Skip to content

Commit 1ca25c9

Browse files
alcoholnicolas-grekas
authored andcommitted
[Routing] Assign attribute aliases to localized route if applicable
1 parent 0798827 commit 1ca25c9

File tree

7 files changed

+92
-7
lines changed

7 files changed

+92
-7
lines changed

Generator/Dumper/CompiledUrlGeneratorDumper.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,15 @@ public function getCompiledAliases(): array
7373
}
7474

7575
$compiledTarget = $target->compile();
76+
$defaults = $target->getDefaults();
77+
78+
if (isset($defaults['_locale']) && str_ends_with($name, '.'.$defaults['_locale'])) {
79+
$defaults['_canonical_route'] = substr($name, 0, -\strlen($defaults['_locale']) - 1);
80+
}
7681

7782
$compiledAliases[$name] = [
7883
$compiledTarget->getVariables(),
79-
$target->getDefaults(),
84+
$defaults,
8085
$target->getRequirements(),
8186
$compiledTarget->getTokens(),
8287
$compiledTarget->getHostTokens(),

Generator/UrlGenerator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ public function generate(string $name, array $parameters = [], int $referenceTyp
108108

109109
if (null !== $locale) {
110110
do {
111-
if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
111+
$route = $this->routes->get($name.'.'.$locale);
112+
if ($route && ($route->getDefault('_canonical_route') === $name || $this->routes->getAlias($name.'.'.$locale))) {
112113
break;
113114
}
114115
} while (false !== $locale = strstr($locale, '_', true));

Loader/AttributeClassLoader.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,18 +241,22 @@ protected function addRoute(RouteCollection $collection, object $attr, array $gl
241241
} else {
242242
$collection->add($name, $route, $priority);
243243
}
244-
foreach ($attr->aliases as $aliasAttribute) {
244+
}
245+
246+
foreach ($attr->aliases as $aliasAttribute) {
247+
$aliasName = $aliasAttribute instanceof DeprecatedAlias ? $aliasAttribute->aliasName : $aliasAttribute;
248+
249+
foreach (array_keys($paths) as $locale) {
250+
$suffix = 0 !== $locale ? '.'.$locale : '';
251+
$alias = $collection->addAlias($aliasName.$suffix, $name.$suffix);
252+
245253
if ($aliasAttribute instanceof DeprecatedAlias) {
246-
$alias = $collection->addAlias($aliasAttribute->aliasName, $name);
247254
$alias->setDeprecated(
248255
$aliasAttribute->package,
249256
$aliasAttribute->version,
250257
$aliasAttribute->message
251258
);
252-
continue;
253259
}
254-
255-
$collection->addAlias($aliasAttribute, $name);
256260
}
257261
}
258262
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures;
13+
14+
use Symfony\Component\Routing\Attribute\Route;
15+
16+
class AliasLocalizedRouteController
17+
{
18+
#[Route(['nl_NL' => '/nl/localized', 'fr_FR' => '/fr/localized'], name: 'localized_route', alias: ['localized_alias'])]
19+
public function localized()
20+
{
21+
}
22+
}

Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,25 @@ public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl()
242242
$this->assertSame('/amusant', $compiledUrlGenerator->generate('fun.fr', ['_locale' => 'en']));
243243
}
244244

245+
public function testLocalizedAliasRouteGeneratesCorrectUrlPerLocale()
246+
{
247+
$this->routeCollection->add('foo.en', (new Route('/en/fork'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo')->setRequirement('_locale', 'en'));
248+
$this->routeCollection->add('foo.fr', (new Route('/fr/fourchette'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo')->setRequirement('_locale', 'fr'));
249+
$this->routeCollection->addAlias('bar.en', 'foo.en');
250+
$this->routeCollection->addAlias('bar.fr', 'foo.fr');
251+
252+
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
253+
254+
$requestContext = new RequestContext();
255+
$requestContext->setParameter('_locale', 'fr');
256+
257+
$compiledUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, $requestContext, null, null);
258+
259+
$this->assertSame('/fr/fourchette', $compiledUrlGenerator->generate('bar'));
260+
$this->assertSame('/en/fork', $compiledUrlGenerator->generate('bar', ['_locale' => 'en']));
261+
$this->assertSame('/fr/fourchette', $compiledUrlGenerator->generate('bar', ['_locale' => 'fr']));
262+
}
263+
245264
public function testAliases()
246265
{
247266
$subCollection = new RouteCollection();

Tests/Generator/UrlGeneratorTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,23 @@ public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl()
291291
$this->assertSame('/app.php/amusant', $urlGenerator->generate('fun.fr', ['_locale' => 'en']));
292292
}
293293

294+
public function testLocalizedAliasRouteGeneratesCorrectUrlPerLocale()
295+
{
296+
$routeCollection = new RouteCollection();
297+
298+
$routeCollection->add('foo.en', (new Route('/en/fork'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo')->setRequirement('_locale', 'en'));
299+
$routeCollection->add('foo.fr', (new Route('/fr/fourchette'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo')->setRequirement('_locale', 'fr'));
300+
$routeCollection->addAlias('bar.en', 'foo.en');
301+
$routeCollection->addAlias('bar.fr', 'foo.fr');
302+
303+
$urlGenerator = $this->getGenerator($routeCollection);
304+
$urlGenerator->getContext()->setParameter('_locale', 'fr');
305+
306+
$this->assertSame('/app.php/fr/fourchette', $urlGenerator->generate('bar'));
307+
$this->assertSame('/app.php/en/fork', $urlGenerator->generate('bar', ['_locale' => 'en']));
308+
$this->assertSame('/app.php/fr/fourchette', $urlGenerator->generate('bar', ['_locale' => 'fr']));
309+
}
310+
294311
public function testGenerateWithoutRoutes()
295312
{
296313
$routes = $this->getRoutes('foo', new Route('/testing/{foo}'));

Tests/Loader/AttributeClassLoaderTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\ActionPathController;
2020
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\AliasClassController;
2121
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\AliasInvokableController;
22+
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\AliasLocalizedRouteController;
2223
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\AliasRouteController;
2324
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\BazClass;
2425
use Symfony\Component\Routing\Tests\Fixtures\AttributeFixtures\DefaultValueController;
@@ -386,6 +387,22 @@ public function testAliasesOnMethod()
386387
$this->assertEquals(new Alias('action_with_alias'), $routes->getAlias('completely_different_name'));
387388
}
388389

390+
public function testLocalizedRouteWithAliases()
391+
{
392+
$routes = $this->loader->load(AliasLocalizedRouteController::class);
393+
$this->assertCount(2, $routes);
394+
395+
$routeNl = $routes->get('localized_route.nl_NL');
396+
$routeFr = $routes->get('localized_route.fr_FR');
397+
398+
$this->assertSame('/nl/localized', $routeNl->getPath());
399+
$this->assertSame('/fr/localized', $routeFr->getPath());
400+
401+
$this->assertNull($routes->getAlias('localized_alias'));
402+
$this->assertEquals(new Alias('localized_route.nl_NL'), $routes->getAlias('localized_alias.nl_NL'));
403+
$this->assertEquals(new Alias('localized_route.fr_FR'), $routes->getAlias('localized_alias.fr_FR'));
404+
}
405+
389406
public function testThrowsWithAliasesOnClass()
390407
{
391408
$this->expectException(\InvalidArgumentException::class);

0 commit comments

Comments
 (0)