Skip to content

Commit 9c08a1c

Browse files
committed
[Routing] Fix i18n routing when the url contains the locale
1 parent dfa118f commit 9c08a1c

File tree

6 files changed

+116
-10
lines changed

6 files changed

+116
-10
lines changed

src/Symfony/Component/Routing/Generator/CompiledUrlGenerator.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ public function generate($name, $parameters = [], $referenceType = self::ABSOLUT
4040
if (null !== $locale) {
4141
do {
4242
if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
43-
unset($parameters['_locale']);
4443
$name .= '.'.$locale;
4544
break;
4645
}
@@ -53,6 +52,16 @@ public function generate($name, $parameters = [], $referenceType = self::ABSOLUT
5352

5453
list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name];
5554

55+
if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) {
56+
if (\in_array('_locale', $variables, true)) {
57+
if (!isset($parameters['_locale'])) {
58+
$parameters['_locale'] = $defaults['_locale'];
59+
}
60+
} else {
61+
unset($parameters['_locale']);
62+
}
63+
}
64+
5665
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
5766
}
5867
}

src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ public function generate($name, $parameters = [], $referenceType = self::ABSOLUT
120120
if (null !== $locale && null !== $name) {
121121
do {
122122
if ((self::$declaredRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
123-
unset($parameters['_locale']);
124123
$name .= '.'.$locale;
125124
break;
126125
}
@@ -133,6 +132,16 @@ public function generate($name, $parameters = [], $referenceType = self::ABSOLUT
133132
134133
list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = self::$declaredRoutes[$name];
135134
135+
if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) {
136+
if (\in_array('_locale', $variables, true)) {
137+
if (!isset($parameters['_locale'])) {
138+
$parameters['_locale'] = $defaults['_locale'];
139+
}
140+
} else {
141+
unset($parameters['_locale']);
142+
}
143+
}
144+
136145
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
137146
}
138147
EOF;

src/Symfony/Component/Routing/Generator/UrlGenerator.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ public function generate($name, $parameters = [], $referenceType = self::ABSOLUT
134134
if (null !== $locale) {
135135
do {
136136
if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
137-
unset($parameters['_locale']);
138137
break;
139138
}
140139
} while (false !== $locale = strstr($locale, '_', true));
@@ -147,7 +146,20 @@ public function generate($name, $parameters = [], $referenceType = self::ABSOLUT
147146
// the Route has a cache of its own and is not recompiled as long as it does not get modified
148147
$compiledRoute = $route->compile();
149148

150-
return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes());
149+
$defaults = $route->getDefaults();
150+
$variables = $compiledRoute->getVariables();
151+
152+
if (isset($defaults['_canonical_route']) && isset($defaults['_locale'])) {
153+
if (\in_array('_locale', $variables, true)) {
154+
if (!isset($parameters['_locale'])) {
155+
$parameters['_locale'] = $defaults['_locale'];
156+
}
157+
} else {
158+
unset($parameters['_locale']);
159+
}
160+
}
161+
162+
return $this->doGenerate($variables, $defaults, $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes());
151163
}
152164

153165
/**

src/Symfony/Component/Routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ public function testDumpWithRouteNotFoundLocalizedRoutes()
131131

132132
public function testDumpWithFallbackLocaleLocalizedRoutes()
133133
{
134-
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_canonical_route', 'test'));
135-
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_canonical_route', 'test'));
136-
$this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_canonical_route', 'test'));
134+
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test'));
135+
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test'));
136+
$this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'test'));
137137

138138
$code = $this->generatorDumper->dump();
139139
file_put_contents($this->testTmpFilepath, $code);
@@ -231,4 +231,29 @@ public function testDumpWithSchemeRequirement()
231231
$this->assertEquals('https://localhost/app.php/testing', $absoluteUrl);
232232
$this->assertEquals('/app.php/testing', $relativeUrl);
233233
}
234+
235+
public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl()
236+
{
237+
$this->routeCollection->add('foo.en', (new Route('/{_locale}/foo'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo'));
238+
$this->routeCollection->add('foo.fr', (new Route('/{_locale}/foo'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo'));
239+
$this->routeCollection->add('fun.en', (new Route('/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'fun'));
240+
$this->routeCollection->add('fun.fr', (new Route('/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'fun'));
241+
242+
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump());
243+
244+
$requestContext = new RequestContext();
245+
$requestContext->setParameter('_locale', 'fr');
246+
247+
$compiledUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, $requestContext, null, null);
248+
249+
$this->assertSame('/fr/foo', $compiledUrlGenerator->generate('foo'));
250+
$this->assertSame('/en/foo', $compiledUrlGenerator->generate('foo.en'));
251+
$this->assertSame('/en/foo', $compiledUrlGenerator->generate('foo', ['_locale' => 'en']));
252+
$this->assertSame('/en/foo', $compiledUrlGenerator->generate('foo.fr', ['_locale' => 'en']));
253+
254+
$this->assertSame('/amusant', $compiledUrlGenerator->generate('fun'));
255+
$this->assertSame('/fun', $compiledUrlGenerator->generate('fun.en'));
256+
$this->assertSame('/fun', $compiledUrlGenerator->generate('fun', ['_locale' => 'en']));
257+
$this->assertSame('/amusant', $compiledUrlGenerator->generate('fun.fr', ['_locale' => 'en']));
258+
}
234259
}

src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@ public function testDumpWithRouteNotFoundLocalizedRoutes()
140140

141141
public function testDumpWithFallbackLocaleLocalizedRoutes()
142142
{
143-
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_canonical_route', 'test'));
144-
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_canonical_route', 'test'));
145-
$this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_canonical_route', 'test'));
143+
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test'));
144+
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test'));
145+
$this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'test'));
146146

147147
$code = $this->generatorDumper->dump([
148148
'class' => 'FallbackLocaleLocalizedProjectUrlGenerator',
@@ -250,4 +250,32 @@ public function testDumpWithSchemeRequirement()
250250
$this->assertEquals('https://localhost/app.php/testing', $absoluteUrl);
251251
$this->assertEquals('/app.php/testing', $relativeUrl);
252252
}
253+
254+
public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl()
255+
{
256+
$this->routeCollection->add('foo.en', (new Route('/{_locale}/foo'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo'));
257+
$this->routeCollection->add('foo.fr', (new Route('/{_locale}/foo'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo'));
258+
$this->routeCollection->add('fun.en', (new Route('/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'fun'));
259+
$this->routeCollection->add('fun.fr', (new Route('/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'fun'));
260+
261+
file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump([
262+
'class' => 'PreserveTheGoodLocaleInTheUrlGenerator',
263+
]));
264+
include $this->testTmpFilepath;
265+
266+
$requestContext = new RequestContext();
267+
$requestContext->setParameter('_locale', 'fr');
268+
269+
$phpGenerator = new \PreserveTheGoodLocaleInTheUrlGenerator($requestContext);
270+
271+
$this->assertSame('/fr/foo', $phpGenerator->generate('foo'));
272+
$this->assertSame('/en/foo', $phpGenerator->generate('foo.en'));
273+
$this->assertSame('/en/foo', $phpGenerator->generate('foo', ['_locale' => 'en']));
274+
$this->assertSame('/en/foo', $phpGenerator->generate('foo.fr', ['_locale' => 'en']));
275+
276+
$this->assertSame('/amusant', $phpGenerator->generate('fun'));
277+
$this->assertSame('/fun', $phpGenerator->generate('fun.en'));
278+
$this->assertSame('/fun', $phpGenerator->generate('fun', ['_locale' => 'en']));
279+
$this->assertSame('/amusant', $phpGenerator->generate('fun.fr', ['_locale' => 'en']));
280+
}
253281
}

src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,29 @@ public function testGenerateWithOverriddenParameterLocaleFromRequestContext()
236236
);
237237
}
238238

239+
public function testDumpWithLocalizedRoutesPreserveTheGoodLocaleInTheUrl()
240+
{
241+
$routeCollection = new RouteCollection();
242+
243+
$routeCollection->add('foo.en', (new Route('/{_locale}/foo'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'foo'));
244+
$routeCollection->add('foo.fr', (new Route('/{_locale}/foo'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'foo'));
245+
$routeCollection->add('fun.en', (new Route('/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'fun'));
246+
$routeCollection->add('fun.fr', (new Route('/amusant'))->setDefault('_locale', 'fr')->setDefault('_canonical_route', 'fun'));
247+
248+
$urlGenerator = $this->getGenerator($routeCollection);
249+
$urlGenerator->getContext()->setParameter('_locale', 'fr');
250+
251+
$this->assertSame('/app.php/fr/foo', $urlGenerator->generate('foo'));
252+
$this->assertSame('/app.php/en/foo', $urlGenerator->generate('foo.en'));
253+
$this->assertSame('/app.php/en/foo', $urlGenerator->generate('foo', ['_locale' => 'en']));
254+
$this->assertSame('/app.php/en/foo', $urlGenerator->generate('foo.fr', ['_locale' => 'en']));
255+
256+
$this->assertSame('/app.php/amusant', $urlGenerator->generate('fun'));
257+
$this->assertSame('/app.php/fun', $urlGenerator->generate('fun.en'));
258+
$this->assertSame('/app.php/fun', $urlGenerator->generate('fun', ['_locale' => 'en']));
259+
$this->assertSame('/app.php/amusant', $urlGenerator->generate('fun.fr', ['_locale' => 'en']));
260+
}
261+
239262
public function testGenerateWithoutRoutes()
240263
{
241264
$this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException');

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy