Файл: symfony-2.7/src/Symfony/Component/Intl/Data/Generator/LocaleDataGenerator.php
Строк: 284
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SymfonyComponentIntlDataGenerator;
use SymfonyComponentFilesystemFilesystem;
use SymfonyComponentIntlDataProviderLanguageDataProvider;
use SymfonyComponentIntlDataProviderRegionDataProvider;
use SymfonyComponentIntlDataProviderScriptDataProvider;
use SymfonyComponentIntlDataUtilLocaleScanner;
use SymfonyComponentIntlExceptionMissingResourceException;
use SymfonyComponentIntlExceptionResourceBundleNotFoundException;
use SymfonyComponentIntlLocale;
/**
* The rule for compiling the locale bundle.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @internal
*/
class LocaleDataGenerator
{
/**
* @var string
*/
private $dirName;
/**
* @var LanguageDataProvider
*/
private $languageDataProvider;
/**
* @var ScriptDataProvider
*/
private $scriptDataProvider;
/**
* @var RegionDataProvider
*/
private $regionDataProvider;
public function __construct($dirName, LanguageDataProvider $languageDataProvider, ScriptDataProvider $scriptDataProvider, RegionDataProvider $regionDataProvider)
{
$this->dirName = $dirName;
$this->languageDataProvider = $languageDataProvider;
$this->scriptDataProvider = $scriptDataProvider;
$this->regionDataProvider = $regionDataProvider;
}
/**
* {@inheritdoc}
*/
public function generateData(GeneratorConfig $config)
{
$filesystem = new Filesystem();
$localeScanner = new LocaleScanner();
$writers = $config->getBundleWriters();
// Prepare filesystem directories
foreach ($writers as $targetDir => $writer) {
$filesystem->remove($targetDir.'/'.$this->dirName);
$filesystem->mkdir($targetDir.'/'.$this->dirName);
}
$locales = $localeScanner->scanLocales($config->getSourceDir().'/locales');
$aliases = $localeScanner->scanAliases($config->getSourceDir().'/locales');
// Flip to facilitate lookup
$flippedLocales = array_flip($locales);
// Don't generate names for aliases (names will be generated for the
// locale they are duplicating)
$displayLocales = array_diff_key($flippedLocales, $aliases);
ksort($displayLocales);
// Generate a list of (existing) locale fallbacks
$fallbackMapping = $this->generateFallbackMapping($displayLocales, $aliases);
$localeNames = array();
// Generate locale names for all locales that have translations in
// at least the language or the region bundle
foreach ($displayLocales as $displayLocale => $_) {
$localeNames[$displayLocale] = array();
foreach ($locales as $locale) {
try {
// Generate a locale name in the language of each display locale
// 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.
if (null !== ($name = $this->generateLocaleName($locale, $displayLocale))) {
$localeNames[$displayLocale][$locale] = $name;
}
} catch (MissingResourceException $e) {
} catch (ResourceBundleNotFoundException $e) {
}
}
}
// Process again to de-duplicate locales and their fallback locales
// Only keep the differences
foreach ($displayLocales as $displayLocale => $_) {
$fallback = $displayLocale;
while (isset($fallbackMapping[$fallback])) {
$fallback = $fallbackMapping[$fallback];
$localeNames[$displayLocale] = array_diff(
$localeNames[$displayLocale],
$localeNames[$fallback]
);
}
// If no names remain to be saved for the current locale, skip it
if (0 === count($localeNames[$displayLocale])) {
continue;
}
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, $displayLocale, array(
'Names' => $localeNames[$displayLocale],
));
}
}
// Generate aliases, needed to enable proper fallback from alias to its
// target
foreach ($aliases as $alias => $aliasOf) {
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, $alias, array(
'%%ALIAS' => $aliasOf,
));
}
}
// Create root file which maps locale codes to locale codes, for fallback
foreach ($writers as $targetDir => $writer) {
$writer->write($targetDir.'/'.$this->dirName, 'meta', array(
'Locales' => $locales,
'Aliases' => $aliases,
));
}
}
private function generateLocaleName($locale, $displayLocale)
{
$name = null;
$lang = Locale::getPrimaryLanguage($locale);
$script = Locale::getScript($locale);
$region = Locale::getRegion($locale);
$variants = Locale::getAllVariants($locale);
// Currently the only available variant is POSIX, which we don't want
// to include in the list
if (count($variants) > 0) {
return;
}
// Some languages are translated together with their region,
// i.e. "en_GB" is translated as "British English"
// we don't include these languages though because they mess up
// the name sorting
// $name = $this->langBundle->getLanguageName($displayLocale, $lang, $region);
// Some languages are simply not translated
// Example: "az" (Azerbaijani) has no translation in "af" (Afrikaans)
if (null === ($name = $this->languageDataProvider->getName($lang, $displayLocale))) {
return;
}
// "as" (Assamese) has no "Variants" block
//if (!$langBundle->get('Variants')) {
// continue;
//}
$extras = array();
// Discover the name of the script part of the locale
// i.e. in zh_Hans_MO, "Hans" is the script
if ($script) {
// Some scripts are not translated into every language
if (null === ($scriptName = $this->scriptDataProvider->getName($script, $displayLocale))) {
return;
}
$extras[] = $scriptName;
}
// Discover the name of the region part of the locale
// i.e. in de_AT, "AT" is the region
if ($region) {
// Some regions are not translated into every language
if (null === ($regionName = $this->regionDataProvider->getName($region, $displayLocale))) {
return;
}
$extras[] = $regionName;
}
if (count($extras) > 0) {
// Remove any existing extras
// For example, in German, zh_Hans is "Chinesisch (vereinfacht)".
// The latter is the script part which is already included in the
// extras and will be appended again with the other extras.
if (preg_match('/^(.+)s+([^)]+)$/', $name, $matches)) {
$name = $matches[1];
}
$name .= ' ('.implode(', ', $extras).')';
}
return $name;
}
private function generateFallbackMapping(array $displayLocales, array $aliases)
{
$mapping = array();
foreach ($displayLocales as $displayLocale => $_) {
$mapping[$displayLocale] = null;
$fallback = $displayLocale;
// Recursively search for a fallback locale until one is found
while (null !== ($fallback = Locale::getFallback($fallback))) {
// Currently, no locale has an alias as fallback locale.
// If this starts to be the case, we need to add code here.
assert(!isset($aliases[$fallback]));
// Check whether the fallback exists
if (isset($displayLocales[$fallback])) {
$mapping[$displayLocale] = $fallback;
break;
}
}
}
return $mapping;
}
}