[Intl] Fix root fallback locale
This commit is contained in:
parent
6c6f76f217
commit
11ff24a665
@ -14,9 +14,6 @@ namespace Symfony\Component\Intl\Data\Generator;
|
||||
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 @@ use Symfony\Component\Intl\Locale;
|
||||
*/
|
||||
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 @@ class LocaleDataGenerator extends AbstractDataGenerator
|
||||
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 @@ class LocaleDataGenerator extends AbstractDataGenerator
|
||||
*/
|
||||
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']);
|
||||
}
|
||||
$pattern = $displayFormat['pattern'] ?? '{0} ({1})';
|
||||
$separator = $displayFormat['separator'] ?? '{0}, {1}';
|
||||
$localeNames = [];
|
||||
@ -110,7 +94,7 @@ class LocaleDataGenerator extends AbstractDataGenerator
|
||||
// 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 @@ class LocaleDataGenerator extends AbstractDataGenerator
|
||||
/**
|
||||
* @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)]));
|
||||
$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) {
|
||||
|
@ -48,6 +48,20 @@ class RegionDataGenerator extends AbstractDataGenerator
|
||||
*/
|
||||
private $regionCodes = [];
|
||||
|
||||
public static function isValidCountryCode($region)
|
||||
{
|
||||
if (isset(self::$blacklist[$region])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// WORLD/CONTINENT/SUBCONTINENT/GROUPING
|
||||
if (ctype_digit($region) || \is_int($region)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -125,12 +139,7 @@ class RegionDataGenerator extends AbstractDataGenerator
|
||||
$regionNames = [];
|
||||
|
||||
foreach ($unfilteredRegionNames as $region => $regionName) {
|
||||
if (isset(self::$blacklist[$region])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// WORLD/CONTINENT/SUBCONTINENT/GROUPING
|
||||
if (ctype_digit($region) || \is_int($region)) {
|
||||
if (!self::isValidCountryCode($region)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ final class Locale extends \Locale
|
||||
* The default fallback locale is used as fallback for locales that have no
|
||||
* fallback otherwise.
|
||||
*
|
||||
* @param string $locale The default fallback locale
|
||||
* @param string|null $locale The default fallback locale
|
||||
*
|
||||
* @see getFallback()
|
||||
*/
|
||||
@ -43,7 +43,7 @@ final class Locale extends \Locale
|
||||
/**
|
||||
* Returns the default fallback locale.
|
||||
*
|
||||
* @return string The default fallback locale
|
||||
* @return string|null The default fallback locale
|
||||
*
|
||||
* @see setDefaultFallback()
|
||||
* @see getFallback()
|
||||
@ -70,7 +70,7 @@ final class Locale extends \Locale
|
||||
if (\function_exists('locale_parse')) {
|
||||
$localeSubTags = locale_parse($locale);
|
||||
if (1 === \count($localeSubTags)) {
|
||||
if (self::$defaultFallback === $localeSubTags['language']) {
|
||||
if ('root' !== self::$defaultFallback && self::$defaultFallback === $localeSubTags['language']) {
|
||||
return 'root';
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ final class Locale extends \Locale
|
||||
return substr($locale, 0, $pos);
|
||||
}
|
||||
|
||||
if (self::$defaultFallback === $locale) {
|
||||
if ('root' !== self::$defaultFallback && self::$defaultFallback === $locale) {
|
||||
return 'root';
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
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;
|
||||
@ -20,9 +18,6 @@ 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 @@ echo "Preparing resource bundle compilation (version $icuVersionInDownload)...\n
|
||||
$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);
|
||||
|
||||
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 @@ $generator->generateData($config);
|
||||
|
||||
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 @@ Date: {$git->getLastAuthoredDate()->format('c')}
|
||||
|
||||
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";
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "az_Latn_AZ"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "bs_Latn_BA"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "en_VU"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "en_ZW"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "ff_Latn_CM"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "ff_Latn_GN"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "ff_Latn_MR"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "ff_Latn_SN"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "id"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "id_ID"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "he"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "he_IL"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "ro"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "nb"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "nb_NO"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "nn_NO"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "pa_Guru_IN"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "pa_Arab_PK"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Latn"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Latn_BA"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Latn_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Latn_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Cyrl_BA"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Cyrl_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Cyrl_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Cyrl_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Latn_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Latn_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Latn_ME"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Cyrl_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Cyrl_XK"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "sr_Cyrl_RS"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "fil"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "fil_PH"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "uz_Arab_AF"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "uz_Latn_UZ"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "zh_Hans_CN"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "zh_Hant_HK"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "zh_Hant_MO"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "zh_Hans_SG"
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"%%ALIAS": "zh_Hant_TW"
|
||||
}
|
@ -46,4 +46,28 @@ class LocaleTest extends TestCase
|
||||
{
|
||||
$this->assertSame($expected, Locale::getFallback($locale));
|
||||
}
|
||||
|
||||
public function testNoDefaultFallback()
|
||||
{
|
||||
$prev = Locale::getDefaultFallback();
|
||||
Locale::setDefaultFallback(null);
|
||||
|
||||
$this->assertSame('nl', Locale::getFallback('nl_NL'));
|
||||
$this->assertNull(Locale::getFallback('nl'));
|
||||
$this->assertNull(Locale::getFallback('root'));
|
||||
|
||||
Locale::setDefaultFallback($prev);
|
||||
}
|
||||
|
||||
public function testDefaultRootFallback()
|
||||
{
|
||||
$prev = Locale::getDefaultFallback();
|
||||
Locale::setDefaultFallback('root');
|
||||
|
||||
$this->assertSame('nl', Locale::getFallback('nl_NL'));
|
||||
$this->assertSame('root', Locale::getFallback('nl'));
|
||||
$this->assertNull(Locale::getFallback('root'));
|
||||
|
||||
Locale::setDefaultFallback($prev);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user