Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9ce27da

Browse 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

File tree

2 files changed

+102
-53
lines changed

2 files changed

+102
-53
lines changed
Lines 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 <[email protected]>
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 <[email protected]>
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

Lines 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)