8000 [Routing] Add fallback to cultureless locale for internationalized ro… · symfony/symfony@bb9ccbf · GitHub
[go: up one dir, main page]

Skip to content

Commit bb9ccbf

Browse files
fancywebnicolas-grekas
authored andcommitted
[Routing] Add fallback to cultureless locale for internationalized routes
1 parent 4b92b96 commit bb9ccbf

File tree

4 files changed

+82
-10
lines changed

4 files changed

+82
-10
lines changed

src/Symfony/Component/Routing/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
4.2.0
5+
-----
6+
7+
* added fallback to cultureless locale for internationalized routes
8+
49
4.0.0
510
-----
611

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,17 @@ public function generate($name, $parameters = array(), $referenceType = self::AB
113113
?? $this->context->getParameter('_locale')
114114
?: $this->defaultLocale;
115115
116-
if (null !== $locale && (self::$declaredRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
117-
unset($parameters['_locale']);
118-
$name .= '.'.$locale;
119-
} elseif (!isset(self::$declaredRoutes[$name])) {
116+
if (null !== $locale) {
117+
do {
118+
if ((self::$declaredRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) {
119+
unset($parameters['_locale']);
120+
$name .= '.'.$locale;
121+
break;
122+
}
123+
} while (false !== $locale = strstr($locale, '_', true));
124+
}
125+
126+
if (!isset(self::$declaredRoutes[$name])) {
120127
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
121128
}
122129

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,21 @@ public function isStrictRequirements()
112112
*/
113113
public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
114114
{
115+
$route = null;
115116
$locale = $parameters['_locale']
116117
?? $this->context->getParameter('_locale')
117118
?: $this->defaultLocale;
118119

119-
if (null !== $locale && null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
120-
unset($parameters['_locale']);
121-
} elseif (null === $route = $this->routes->get($name)) {
120+
if (null !== $locale) {
121+
do {
122+
if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) {
123+
unset($parameters['_locale']);
124+
break;
125+
}
126+
} while (false !== $locale = strstr($locale, '_', true));
127+
}
128+
129+
if (null === $route = $route ?? $this->routes->get($name)) {
122130
throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
123131
}
124132

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

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,20 @@ public function testDumpWithRoutes()
8484
$this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter);
8585
}
8686

87-
public function testDumpWithLocalizedRoutes()
87+
public function testDumpWithSimpleLocalizedRoutes()
8888
{
89+
$this->routeCollection->add('test', (new Route('/foo')));
8990
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test'));
9091
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test'));
9192

9293
$code = $this->generatorDumper->dump(array(
93-
'class' => 'LocalizedProjectUrlGenerator',
94+
'class' => 'SimpleLocalizedProjectUrlGenerator',
9495
));
9596
file_put_contents($this->testTmpFilepath, $code);
9697
include $this->testTmpFilepath;
9798

9899
$context = new RequestContext('/app.php');
99-
$projectUrlGenerator = new \LocalizedProjectUrlGenerator($context, null, 'en');
100+
$projectUrlGenerator = new \SimpleLocalizedProjectUrlGenerator($context, null, 'en');
100101

101102
$urlWithDefaultLocale = $projectUrlGenerator->generate('test');
102103
$urlWithSpecifiedLocale = $projectUrlGenerator->generate('test', array('_locale' => 'nl'));
@@ -109,6 +110,57 @@ public function testDumpWithLocalizedRoutes()
109110
$this->assertEquals('/app.php/testen/is/leuk', $urlWithSpecifiedLocale);
110111
$this->assertEquals('/app.php/testing/is/fun', $urlWithEnglishContext);
111112
$this->assertEquals('/app.php/testen/is/leuk', $urlWithDutchContext);
113+
114+
// test with full route name
115+
$this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test.en'));
116+
117+
$context->setParameter('_locale', 'de_DE');
118+
// test that it fall backs to another route when there is no matching localized route
119+
$this->assertEquals('/app.php/foo', $projectUrlGenerator->generate('test'));
120+
}
121+
122+
/**
123+
* @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException
124+
* @expectedExceptionMessage Unable to generate a URL for the named route "test" as such route does not exist.
125+
*/
126+
public function testDumpWithRouteNotFoundLocalizedRoutes()
127+
{
128+
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test'));
129+
130+
$code = $this->generatorDumper->dump(array(
131+
'class' => 'RouteNotFoundLocalizedProjectUrlGenerator',
132+
));
133+
file_put_contents($this->testTmpFilepath, $code);
134+
include $this->testTmpFilepath;
135+
136+
$projectUrlGenerator = new \RouteNotFoundLocalizedProjectUrlGenerator(new RequestContext('/app.php'), null, 'pl_PL');
137+
$projectUrlGenerator->generate('test');
138+
}
139+
140+
public function testDumpWithFallbackLocaleLocalizedRoutes()
141+
{
142+
$this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_canonical_route', 'test'));
143+
$this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_canonical_route', 'test'));
144+
$this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_canonical_route', 'test'));
145+
146+
$code = $this->generatorDumper->dump(array(
147+
'class' => 'FallbackLocaleLocalizedProjectUrlGenerator',
148+
));
149+
file_put_contents($this->testTmpFilepath, $code);
150+
include $this->testTmpFilepath;
151+
152+
$context = new RequestContext('/app.php');
153+
$context->setParameter('_locale', 'en_GB');
154+
$projectUrlGenerator = new \FallbackLocaleLocalizedProjectUrlGenerator($context, null, null);
155+
156+
// test with context _locale
157+
$this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test'));
158+
// test with parameters _locale
159+
$this->assertEquals('/app.php/testen/is/leuk', $projectUrlGenerator->generate('test', array('_locale' => 'nl_BE')));
160+
161+
$projectUrlGenerator = new \FallbackLocaleLocalizedProjectUrlGenerator(new RequestContext('/app.php'), null, 'fr_CA');
162+
// test with default locale
163+
$this->assertEquals('/app.php/tester/est/amusant', $projectUrlGenerator->generate('test'));
112164
}
113165

114166
public function testDumpWithTooManyRoutes()

0 commit comments

Comments
 (0)
0