Skip to content

Commit e24d8e6

Browse files
committed
[Intl][4.2] Add FallbackTrait for data generation
1 parent 74cbe5a commit e24d8e6

File tree

2 files changed

+97
-55
lines changed

2 files changed

+97
-55
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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+
private function generateFallbackData(BundleEntryReaderInterface $reader, string $tempDir, string $displayLocale): array
47+
{
48+
if (null === $fallback = Locale::getFallback($displayLocale)) {
49+
return [];
50+
}
51+
52+
if (isset($this->fallbackCache[$fallback])) {
53+
return $this->fallbackCache[$fallback];
54+
}
55+
56+
$prevGeneratingFallback = $this->generatingFallback;
57+
$this->generatingFallback = true;
58+
59+
try {
60+
$data = 'root' === $fallback ? $this->generateDataForRoot($reader, $tempDir) : $this->generateDataForLocale($reader, $tempDir, $fallback);
61+
} finally {
62+
$this->generatingFallback = $prevGeneratingFallback;
63+
}
64+
65+
return $this->fallbackCache[$fallback] = $data ?: [];
66+
}
67+
}

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

Lines changed: 30 additions & 55 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,11 +27,11 @@
2827
*/
2928
class LocaleDataGenerator extends AbstractDataGenerator
3029
{
31-
private $locales;
32-
private $localeAliases;
33-
private $localeParents;
34-
private $fallbackMapping;
35-
private $fallbackCache = [];
30+
use FallbackTrait;
31+
32+
private $locales = [];
33+
private $localeAliases = [];
34+
private $localeParents = [];
3635

3736
/**
3837
* {@inheritdoc}
@@ -42,7 +41,6 @@ protected function scanLocales(LocaleScanner $scanner, $sourceDir)
4241
$this->locales = $scanner->scanLocales($sourceDir.'/locales');
4342
$this->localeAliases = $scanner->scanAliases($sourceDir.'/locales');
4443
$this->localeParents = $scanner->scanParents($sourceDir.'/locales');
45-
$this->fallbackMapping = $this->generateFallbackMapping(array_diff($this->locales, array_keys($this->localeAliases)), $this->localeAliases);
4644

4745
return $this->locales;
4846
}
@@ -66,8 +64,6 @@ protected function compileTemporaryBundles(BundleCompilerInterface $compiler, $s
6664
*/
6765
protected function preGenerate()
6866
{
69-
$this->fallbackCache = [];
70-
7167
// Write parents locale file for the Translation component
7268
\file_put_contents(
7369
__DIR__.'/../../../Translation/Resources/data/parents.json',
@@ -81,7 +77,8 @@ protected function preGenerate()
8177
protected function generateDataForLocale(BundleEntryReaderInterface $reader, $tempDir, $displayLocale)
8278
{
8379
// Don't generate aliases, as they are resolved during runtime
84-
if (isset($this->localeAliases[$displayLocale])) {
80+
// Unless an alias is needed as fallback for de-duplication purposes
81+
if (isset($this->localeAliases[$displayLocale]) && !$this->generatingFallback) {
8582
return;
8683
}
8784

@@ -93,7 +90,7 @@ protected function generateDataForLocale(BundleEntryReaderInterface $reader, $te
9390
$localeNames = [];
9491
foreach ($this->locales as $locale) {
9592
// Ensure a normalized list of pure locales
96-
if (isset($this->localeAliases[$displayLocale]) || \Locale::getAllVariants($locale)) {
93+
if (\Locale::getAllVariants($locale)) {
9794
continue;
9895
}
9996

@@ -110,21 +107,27 @@ protected function generateDataForLocale(BundleEntryReaderInterface $reader, $te
110107
}
111108
}
112109

113-
// Process again to de-duplicate locales and their fallback locales
114-
// Only keep the differences
115-
$fallback = $displayLocale;
116-
while (isset($this->fallbackMapping[$fallback])) {
117-
if (!isset($this->fallbackCache[$fallback = $this->fallbackMapping[$fallback]])) {
118-
$this->fallbackCache[$fallback] = $this->generateDataForLocale($reader, $tempDir, $fallback) ?: [];
119-
}
120-
if (isset($this->fallbackCache[$fallback]['Names'])) {
121-
$localeNames = array_diff($localeNames, $this->fallbackCache[$fallback]['Names']);
122-
}
110+
$data = [
111+
'Names' => $localeNames,
112+
];
113+
114+
// Don't de-duplicate a fallback locale
115+
// Ensures the display locale can be de-duplicated on itself
116+
if ($this->generatingFallback) {
117+
return $data;
123118
}
124119

125-
if ($localeNames) {
126-
return ['Names' => $localeNames];
120+
// Process again to de-duplicate locale and its fallback locales
121+
// Only keep the differences
122+
$fallbackData = $this->generateFallbackData($reader, $tempDir, $displayLocale);
123+
if (isset($fallbackData['Names'])) {
124+
$data['Names'] = array_diff($data['Names'], $fallbackData['Names']);
125+
}
126+
if (!$data['Names']) {
127+
return;
127128
}
129+
130+
return $data;
128131
}
129132

130133
/**
@@ -139,12 +142,10 @@ protected function generateDataForRoot(BundleEntryReaderInterface $reader, $temp
139142
*/
140143
protected function generateDataForMeta(BundleEntryReaderInterface $reader, $tempDir)
141144
{
142-
if ($this->locales || $this->localeAliases) {
143-
return [
144-
'Locales' => $this->locales,
145-
'Aliases' => $this->localeAliases,
146-
];
147-
}
145+
return [
146+
'Locales' => $this->locales,
147+
'Aliases' => $this->localeAliases,
148+
];
148149
}
149150

150151
/**
@@ -183,30 +184,4 @@ private function generateLocaleName(BundleEntryReaderInterface $reader, $tempDir
183184

184185
return $name;
185186
}
186-
187-
private function generateFallbackMapping(array $displayLocales, array $aliases)
188-
{
189-
$displayLocales = array_flip($displayLocales);
190-
$mapping = [];
191-
192-
foreach ($displayLocales as $displayLocale => $_) {
193-
$mapping[$displayLocale] = null;
194-
$fallback = $displayLocale;
195-
196-
// Recursively search for a fallback locale until one is found
197-
while (null !== ($fallback = Locale::getFallback($fallback))) {
198-
// Currently, no locale has an alias as fallback locale.
199-
// If this starts to be the case, we need to add code here.
200-
\assert(!isset($aliases[$fallback]));
201-
202-
// Check whether the fallback exists
203-
if (isset($displayLocales[$fallback])) {
204-
$mapping[$displayLocale] = $fallback;
205-
break;
206-
}
207-
}
208-
}
209-
210-
return $mapping;
211-
}
212187
}

0 commit comments

Comments
 (0)