Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9ce27da

Browse filesBrowse files
minor #31432 [Intl] Add FallbackTrait for data generation (ro0NL)
This PR was merged into the 3.4 branch. Discussion ---------- [Intl] Add FallbackTrait for data generation | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | #... <!-- #-prefixed issue number(s), if any --> | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> This is the last architectural change for the Intl data compilation. Promised. It fixes de-duplicating a locale from its fallback locale. The problem is it uses a while-loop, comparing the locale to each fallback locale. Given - `root` (val=A) - `ur` (val=B) - `ur_IN` (val=A) We have an edge case where a locale (ur_IN) override its fallback locale (ur), setting/restoring the value back to the root locale. This happens for the GMT format in the timezone bundle i know of ... in this case the `ur_IN` locale needs to write its own value. The current approach is a while-loop comparing each fallback locale (ur, root) to the current locale (ur_IN). Eventually comparing `ur_IN <> root`, which causes a wrong diff, as such `ur_IN` falls back to `ur` providing the wrong value (val=B, where val=A is expected). The new approach uses recursion so we only compare `ur <> ur_IN`, where `ur_IN` on itself is compared to `root`. 4.2) https://github.com/ro0NL/symfony/commit/e24d8e6 4.3) https://github.com/ro0NL/symfony/commit/31591d0 Commits ------- 36ddfd5 [Intl] Add FallbackTrait for data generation
2 parents 16f1418 + 36ddfd5 commit 9ce27da
Copy full SHA for 9ce27da

File tree

2 files changed

+102
-53
lines changed
Filter options

2 files changed

+102
-53
lines changed
+73Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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\Intl\Data\Generator;
13+
14+
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
15+
use Symfony\Component\Intl\Locale;
16+
17+
/**
18+
* @author Roland Franssen <franssen.roland@gmail.com>
19+
*
20+
* @internal
21+
*/
22+
trait FallbackTrait
23+
{
24+
private $fallbackCache = [];
25+
private $generatingFallback = false;
26+
27+
/**
28+
* @param string $tempDir
29+
* @param string $displayLocale
30+
*
31+
* @return array|null
32+
*
33+
* @see AbstractDataGenerator::generateDataForLocale()
34+
*/
35+
abstract protected function generateDataForLocale(BundleEntryReaderInterface $reader, $tempDir, $displayLocale);
36+
37+
/**
38+
* @param string $tempDir
39+
*
40+
* @return array|null
41+
*
42+
* @see AbstractDataGenerator::generateDataForRoot()
43+
*/
44+
abstract protected function generateDataForRoot(BundleEntryReaderInterface $reader, $tempDir);
45+
46+
/**
47+
* @param string $tempDir
48+
* @param string $displayLocale
49+
*
50+
* @return array
51+
*/
52+
private function generateFallbackData(BundleEntryReaderInterface $reader, $tempDir, $displayLocale)
53+
{
54+
if (null === $fallback = Locale::getFallback($displayLocale)) {
55+
return [];
56+
}
57+
58+
if (isset($this->fallbackCache[$fallback])) {
59+
return $this->fallbackCache[$fallback];
60+
}
61+
62+
$prevGeneratingFallback = $this->generatingFallback;
63+
$this->generatingFallback = true;
64+
65+
try {
66+
$data = 'root' === $fallback ? $this->generateDataForRoot($reader, $tempDir) : $this->generateDataForLocale($reader, $tempDir, $fallback);
67+
} finally {
68+
$this->generatingFallback = $prevGeneratingFallback;
69+
}
70+
71+
return $this->fallbackCache[$fallback] = $data ?: [];
72+
}
73+
}

‎src/Symfony/Component/Intl/Data/Generator/LocaleDataGenerator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Intl/Data/Generator/LocaleDataGenerator.php
+29-53Lines changed: 29 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
1717
use Symfony\Component\Intl\Data\Util\LocaleScanner;
1818
use Symfony\Component\Intl\Exception\MissingResourceException;
19-
use Symfony\Component\Intl\Locale;
2019

2120
/**
2221
* The rule for compiling the locale bundle.
@@ -28,10 +27,10 @@
2827
*/
2928
class LocaleDataGenerator extends AbstractDataGenerator
3029
{
31-
private $locales;
32-
private $localeAliases;
33-
private $fallbackMapping;
34-
private $fallbackCache = [];
30+
use FallbackTrait;
31+
32+
private $locales = [];
33+
private $localeAliases = [];
3534

3635
/**
3736
* {@inheritdoc}
@@ -40,7 +39,6 @@ protected function scanLocales(LocaleScanner $scanner, $sourceDir)
4039
{
4140
$this->locales = $scanner->scanLocales($sourceDir.'/locales');
4241
$this->localeAliases = $scanner->scanAliases($sourceDir.'/locales');
43-
$this->fallbackMapping = $this->generateFallbackMapping(array_diff($this->locales, array_keys($this->localeAliases)), $this->localeAliases);
4442

4543
return $this->locales;
4644
}
@@ -64,7 +62,6 @@ protected function compileTemporaryBundles(BundleCompilerInterface $compiler, $s
6462
*/
6563
protected function preGenerate()
6664
{
67-
$this->fallbackCache = [];
6865
}
6966

7067
/**
@@ -73,7 +70,8 @@ protected function preGenerate()
7370
protected function generateDataForLocale(BundleEntryReaderInterface $reader, $tempDir, $displayLocale)
7471
{
7572
// Don't generate aliases, as they are resolved during runtime
76-
if (isset($this->localeAliases[$displayLocale])) {
73+
// Unless an alias is needed as fallback for de-duplication purposes
74+
if (isset($this->localeAliases[$displayLocale]) && !$this->generatingFallback) {
7775
return;
7876
}
7977

@@ -85,7 +83,7 @@ protected function generateDataForLocale(BundleEntryReaderInterface $reader, $te
8583
$localeNames = [];
8684
foreach ($this->locales as $locale) {
8785
// Ensure a normalized list of pure locales
88-
if (isset($this->localeAliases[$displayLocale]) || \Locale::getAllVariants($locale)) {
86+
if (\Locale::getAllVariants($locale)) {
8987
continue;
9088
}
9189

@@ -102,21 +100,27 @@ protected function generateDataForLocale(BundleEntryReaderInterface $reader, $te
102100
}
103101
}
104102

105-
// Process again to de-duplicate locales and their fallback locales
106-
// Only keep the differences
107-
$fallback = $displayLocale;
108-
while (isset($this->fallbackMapping[$fallback])) {
109-
if (!isset($this->fallbackCache[$fallback = $this->fallbackMapping[$fallback]])) {
110-
$this->fallbackCache[$fallback] = $this->generateDataForLocale($reader, $tempDir, $fallback) ?: [];
111-
}
112-
if (isset($this->fallbackCache[$fallback]['Names'])) {
113-
$localeNames = array_diff($localeNames, $this->fallbackCache[$fallback]['Names']);
114-
}
103+
$data = [
104+
'Names' => $localeNames,
105+
];
106+
107+
// Don't de-duplicate a fallback locale
108+
// Ensures the display locale can be de-duplicated on itself
109+
if ($this->generatingFallback) {
110+
return $data;
115111
}
116112

117-
if ($localeNames) {
118-
return ['Names' => $localeNames];
113+
// Process again to de-duplicate locale and its fallback locales
114+
// Only keep the differences
115+
$fallbackData = $this->generateFallbackData($reader, $tempDir, $displayLocale);
116+
if (isset($fallbackData['Names'])) {
117+
$data['Names'] = array_diff($data['Names'], $fallbackData['Names']);
118+
}
119+
if (!$data['Names']) {
120+
return;
119121
}
122+
123+
return $data;
120124
}
121125

122126
/**
@@ -131,12 +135,10 @@ protected function generateDataForRoot(BundleEntryReaderInterface $reader, $temp
131135
*/
132136
protected function generateDataForMeta(BundleEntryReaderInterface $reader, $tempDir)
133137
{
134-
if ($this->locales || $this->localeAliases) {
135-
return [
136-
'Locales' => $this->locales,
137-
'Aliases' => $this->localeAliases,
138-
];
139-
}
138+
return [
139+
'Locales' => $this->locales,
140+
'Aliases' => $this->localeAliases,
141+
];
140142
}
141143

142144
/**
@@ -175,30 +177,4 @@ private function generateLocaleName(BundleEntryReaderInterface $reader, $tempDir
175177

176178
return $name;
177179
}
178-
179-
private function generateFallbackMapping(array $displayLocales, array $aliases)
180-
{
181-
$displayLocales = array_flip($displayLocales);
182-
$mapping = [];
183-
184-
foreach ($displayLocales as $displayLocale => $_) {
185-
$mapping[$displayLocale] = null;
186-
$fallback = $displayLocale;
187-
188-
// Recursively search for a fallback locale until one is found
189-
while (null !== ($fallback = Locale::getFallback($fallback))) {
190-
// Currently, no locale has an alias as fallback locale.
191-
// If this starts to be the case, we need to add code here.
192-
\assert(!isset($aliases[$fallback]));
193-
194-
// Check whether the fallback exists
195-
if (isset($displayLocales[$fallback])) {
196-
$mapping[$displayLocale] = $fallback;
197-
break;
198-
}
199-
}
200-
}
201-
202-
return $mapping;
203-
}
204180
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.