-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Intl] Fix root fallback locale #31411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,9 +14,6 @@ | |
use Symfony\Component\Filesystem\Filesystem; | ||
use Symfony\Component\Intl\Data\Bundle\Compiler\BundleCompilerInterface; | ||
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface; | ||
use Symfony\Component\Intl\Data\Provider\LanguageDataProvider; | ||
use Symfony\Component\Intl\Data\Provider\RegionDataProvider; | ||
use Symfony\Component\Intl\Data\Provider\ScriptDataProvider; | ||
use Symfony\Component\Intl\Data\Util\LocaleScanner; | ||
use Symfony\Component\Intl\Exception\MissingResourceException; | ||
use Symfony\Component\Intl\Locale; | ||
|
@@ -31,23 +28,11 @@ | |
*/ | ||
class LocaleDataGenerator extends AbstractDataGenerator | ||
{ | ||
private $languageDataProvider; | ||
private $scriptDataProvider; | ||
private $regionDataProvider; | ||
private $locales; | ||
private $localeAliases; | ||
private $fallbackMapping; | ||
private $fallbackCache = []; | ||
|
||
public function __construct(BundleCompilerInterface $compiler, $dirName, LanguageDataProvider $languageDataProvider, ScriptDataProvider $scriptDataProvider, RegionDataProvider $regionDataProvider) | ||
{ | ||
parent::__construct($compiler, $dirName); | ||
|
||
$this->languageDataProvider = $languageDataProvider; | ||
$this->scriptDataProvider = $scriptDataProvider; | ||
$this->regionDataProvider = $regionDataProvider; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
|
@@ -66,8 +51,12 @@ protected function scanLocales(LocaleScanner $scanner, $sourceDir) | |
protected function compileTemporaryBundles(BundleCompilerInterface $compiler, $sourceDir, $tempDir) | ||
{ | ||
$filesystem = new Filesystem(); | ||
$filesystem->mkdir($tempDir.'/lang'); | ||
$filesystem->mkdir([ | ||
$tempDir.'/lang', | ||
$tempDir.'/region', | ||
]); | ||
$compiler->compile($sourceDir.'/lang', $tempDir.'/lang'); | ||
$compiler->compile($sourceDir.'/region', $tempDir.'/region'); | ||
} | ||
|
||
/** | ||
|
@@ -83,19 +72,14 @@ protected function preGenerate() | |
*/ | ||
protected function generateDataForLocale(BundleEntryReaderInterface $reader, $tempDir, $displayLocale) | ||
{ | ||
// Generate aliases, needed to enable proper fallback from alias to its | ||
// target | ||
// Don't generate aliases, as they are resolved during runtime | ||
if (isset($this->localeAliases[$displayLocale])) { | ||
return ['%%ALIAS' => $this->localeAliases[$displayLocale]]; | ||
return; | ||
} | ||
|
||
// Generate locale names for all locales that have translations in | ||
// at least the language or the region bundle | ||
try { | ||
$displayFormat = $reader->readEntry($tempDir.'/lang', $displayLocale, ['localeDisplayPattern']); | ||
} catch (MissingResourceException $e) { | ||
$displayFormat = $reader->readEntry($tempDir.'/lang', 'root', ['localeDisplayPattern']); | ||
} | ||
$displayFormat = $reader->readEntry($tempDir.'/lang', $displayLocale, ['localeDisplayPattern']); | ||
$pattern = $displayFormat['pattern'] ?? '{0} ({1})'; | ||
$separator = $displayFormat['separator'] ?? '{0}, {1}'; | ||
$localeNames = []; | ||
|
@@ -110,7 +94,7 @@ protected function generateDataForLocale(BundleEntryReaderInterface $reader, $te | |
// Each locale name has the form: "Language (Script, Region, Variant1, ...) | ||
// Script, Region and Variants are optional. If none of them is | ||
// available, the braces are not printed. | ||
$localeNames[$locale] = $this->generateLocaleName($locale, $displayLocale, $pattern, $separator); | ||
$localeNames[$locale] = $this->generateLocaleName($reader, $tempDir, $locale, $displayLocale, $pattern, $separator); | ||
} catch (MissingResourceException $e) { | ||
// Silently ignore incomplete locale names | ||
// In this case one should configure at least one fallback locale that is complete (e.g. English) during | ||
|
@@ -158,22 +142,26 @@ protected function generateDataForMeta(BundleEntryReaderInterface $reader, $temp | |
/** | ||
* @return string | ||
*/ | ||
private function generateLocaleName($locale, $displayLocale, $pattern, $separator) | ||
private function generateLocaleName(BundleEntryReaderInterface $reader, $tempDir, $locale, $displayLocale, $pattern, $separator) | ||
{ | ||
// Apply generic notation using square brackets as described per http://cldr.unicode.org/translation/language-names | ||
$name = str_replace(['(', ')'], ['[', ']'], $this->languageDataProvider->getName(\Locale::getPrimaryLanguage($locale), $displayLocale)); | ||
$name = str_replace(['(', ')'], ['[', ']'], $reader->readEntry($tempDir.'/lang', $displayLocale, ['Languages', \Locale::getPrimaryLanguage($locale)])); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. now uses
moreover, this allows to keep the generators decoupled |
||
$extras = []; | ||
|
||
// Discover the name of the script part of the locale | ||
// i.e. in zh_Hans_MO, "Hans" is the script | ||
if ($script = \Locale::getScript($locale)) { | ||
$extras[] = str_replace(['(', ')'], ['[', ']'], $this->scriptDataProvider->getName($script, $displayLocale)); | ||
$extras[] = str_replace(['(', ')'], ['[', ']'], $reader->readEntry($tempDir.'/lang', $displayLocale, ['Scripts', $script])); | ||
} | ||
|
||
// Discover the name of the region part of the locale | ||
// i.e. in de_AT, "AT" is the region | ||
if ($region = \Locale::getRegion($locale)) { | ||
$extras[] = str_replace(['(', ')'], ['[', ']'], $this->regionDataProvider->getName($region, $displayLocale)); | ||
if (!RegionDataGenerator::isValidCountryCode($region)) { | ||
throw new MissingResourceException('Skipping "'.$locale.'" due an invalid country.'); | ||
} | ||
|
||
$extras[] = str_replace(['(', ')'], ['[', ']'], $reader->readEntry($tempDir.'/region', $displayLocale, ['Countries', $region])); | ||
} | ||
|
||
if ($extras) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,18 +11,13 @@ | |
|
||
use Symfony\Component\Filesystem\Filesystem; | ||
use Symfony\Component\Intl\Data\Bundle\Compiler\GenrbCompiler; | ||
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReader; | ||
use Symfony\Component\Intl\Data\Bundle\Reader\JsonBundleReader; | ||
use Symfony\Component\Intl\Data\Bundle\Writer\JsonBundleWriter; | ||
use Symfony\Component\Intl\Data\Generator\CurrencyDataGenerator; | ||
use Symfony\Component\Intl\Data\Generator\GeneratorConfig; | ||
use Symfony\Component\Intl\Data\Generator\LanguageDataGenerator; | ||
use Symfony\Component\Intl\Data\Generator\LocaleDataGenerator; | ||
use Symfony\Component\Intl\Data\Generator\RegionDataGenerator; | ||
use Symfony\Component\Intl\Data\Generator\ScriptDataGenerator; | ||
use Symfony\Component\Intl\Data\Provider\LanguageDataProvider; | ||
use Symfony\Component\Intl\Data\Provider\RegionDataProvider; | ||
use Symfony\Component\Intl\Data\Provider\ScriptDataProvider; | ||
use Symfony\Component\Intl\Intl; | ||
use Symfony\Component\Intl\Locale; | ||
use Symfony\Component\Intl\Util\GitRepository; | ||
|
@@ -171,27 +166,13 @@ | |
$compiler = new GenrbCompiler($genrb, $genrbEnv); | ||
$config = new GeneratorConfig($sourceDir.'/data', $icuVersionInDownload); | ||
$jsonDir = dirname(__DIR__).'/data'; | ||
$targetDirs = [$jsonDir]; | ||
$workingDirs = [$jsonDir]; | ||
|
||
$config->addBundleWriter($jsonDir, new JsonBundleWriter()); | ||
|
||
echo "Starting resource bundle compilation. This may take a while...\n"; | ||
|
||
$filesystem->remove($workingDirs); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is done in each generator already |
||
|
||
foreach ($workingDirs as $targetDir) { | ||
$filesystem->mkdir([ | ||
$targetDir.'/'.Intl::CURRENCY_DIR, | ||
$targetDir.'/'.Intl::LANGUAGE_DIR, | ||
$targetDir.'/'.Intl::LOCALE_DIR, | ||
$targetDir.'/'.Intl::REGION_DIR, | ||
$targetDir.'/'.Intl::SCRIPT_DIR, | ||
]); | ||
} | ||
|
||
// We don't want to use fallback to English during generation | ||
Locale::setDefaultFallback(null); | ||
Locale::setDefaultFallback('root'); | ||
|
||
echo "Generating language data...\n"; | ||
|
||
|
@@ -215,14 +196,7 @@ | |
|
||
echo "Generating locale data...\n"; | ||
|
||
$reader = new BundleEntryReader(new JsonBundleReader()); | ||
$generator = new LocaleDataGenerator( | ||
$compiler, | ||
Intl::LOCALE_DIR, | ||
new LanguageDataProvider($jsonDir.'/'.Intl::LANGUAGE_DIR, $reader), | ||
new ScriptDataProvider($jsonDir.'/'.Intl::SCRIPT_DIR, $reader), | ||
new RegionDataProvider($jsonDir.'/'.Intl::REGION_DIR, $reader) | ||
); | ||
$generator = new LocaleDataGenerator($compiler, Intl::LOCALE_DIR); | ||
$generator->generateData($config); | ||
|
||
echo "Resource bundle compilation complete.\n"; | ||
|
@@ -238,18 +212,15 @@ | |
|
||
GIT_INFO; | ||
|
||
foreach ($targetDirs as $targetDir) { | ||
$gitInfoFile = $targetDir.'/git-info.txt'; | ||
$gitInfoFile = $jsonDir.'/git-info.txt'; | ||
|
||
file_put_contents($gitInfoFile, $gitInfo); | ||
file_put_contents($gitInfoFile, $gitInfo); | ||
|
||
echo "Wrote $gitInfoFile.\n"; | ||
echo "Wrote $gitInfoFile.\n"; | ||
|
||
$versionFile = $targetDir.'/version.txt'; | ||
$versionFile = $jsonDir.'/version.txt'; | ||
|
||
file_put_contents($versionFile, "$icuVersionInDownload\n"); | ||
|
||
echo "Wrote $versionFile.\n"; | ||
} | ||
file_put_contents($versionFile, "$icuVersionInDownload\n"); | ||
|
||
echo "Wrote $versionFile.\n"; | ||
echo "Done.\n"; |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defaulting to root during compile makes things like this more straightforward (the timezone generator in master also benefits)
i've verified it causes no side-effects in 4.2 / master 👍