Skip to content

Commit 423d3dd

Browse files
bug #35101 [Routing] Fix i18n routing when the url contains the locale (fancyweb)
This PR was merged into the 4.3 branch. Discussion ---------- [Routing] Fix i18n routing when the url contains the locale | Q | A | ------------- | --- | Branch? | 4.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | #34469 | License | MIT | Doc PR | - This PR fixes different scenarios with i18n routing. Commits ------- cd40bb8 [Routing] Fix i18n routing when the url contains the locale
2 parents cbf2abd + cd40bb8 commit 423d3dd

File tree

6 files changed

+110
-10
lines changed

6 files changed

+110
-10
lines changed

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

Lines changed: 8 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,14 @@ 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+
unset($parameters['_locale']);
58+
} elseif (!isset($parameters['_locale'])) {
59+
$parameters['_locale'] = $defaults['_locale'];
60+
}
61+
}
62+
5663
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
5764
}
5865
}

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

Lines changed: 8 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,14 @@ 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+
unset($parameters['_locale']);
138+
} elseif (!isset($parameters['_locale'])) {
139+
$parameters['_locale'] = $defaults['_locale'];
140+
}
141+
}
142+
136143
return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes);
137144
}
138145
EOF;

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

Lines changed: 12 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,18 @@ 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+
unset($parameters['_locale']);
155+
} elseif (!isset($parameters['_locale'])) {
156+
$parameters['_locale'] = $defaults['_locale'];
157+
}
158+
}
159+
160+
return $this->doGenerate($variables, $defaults, $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens(), $route->getSchemes());
151161
}
152162

153163
/**

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