]> git.immae.eu Git - github/wallabag/wallabag.git/blame - vendor/symfony/intl/Symfony/Component/Intl/ResourceBundle/Transformer/Rule/LocaleBundleTransformationRule.php
gitignore vendor
[github/wallabag/wallabag.git] / vendor / symfony / intl / Symfony / Component / Intl / ResourceBundle / Transformer / Rule / LocaleBundleTransformationRule.php
CommitLineData
4f5b44bd
NL
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
12namespace Symfony\Component\Intl\ResourceBundle\Transformer\Rule;
13
14use Symfony\Component\Intl\Exception\RuntimeException;
15use Symfony\Component\Intl\Intl;
16use Symfony\Component\Intl\ResourceBundle\Transformer\CompilationContextInterface;
17use Symfony\Component\Intl\ResourceBundle\Transformer\StubbingContextInterface;
18use Symfony\Component\Intl\ResourceBundle\Writer\TextBundleWriter;
19
20/**
21 * The rule for compiling the locale bundle.
22 *
23 * @author Bernhard Schussek <bschussek@gmail.com>
24 */
25class LocaleBundleTransformationRule implements TransformationRuleInterface
26{
27 /**
28 * @var \Symfony\Component\Intl\ResourceBundle\LanguageBundleInterface
29 */
30 private $languageBundle;
31
32 /**
33 * @var \Symfony\Component\Intl\ResourceBundle\RegionBundleInterface
34 */
35 private $regionBundle;
36
37 public function __construct()
38 {
39 $this->languageBundle = Intl::getLanguageBundle();
40 $this->regionBundle = Intl::getRegionBundle();
41 }
42
43 /**
44 * {@inheritdoc}
45 */
46 public function getBundleName()
47 {
48 return 'locales';
49 }
50
51 /**
52 * {@inheritdoc}
53 */
54 public function beforeCompile(CompilationContextInterface $context)
55 {
56 $tempDir = sys_get_temp_dir() . '/icu-data-locales';
57
58 $context->getFilesystem()->remove($tempDir);
59 $context->getFilesystem()->mkdir($tempDir);
60
61 $this->generateTextFiles($tempDir, $this->scanLocales($context));
62
63 return $tempDir;
64 }
65
66 /**
67 * {@inheritdoc}
68 */
69 public function afterCompile(CompilationContextInterface $context)
70 {
71 $context->getFilesystem()->remove(sys_get_temp_dir() . '/icu-data-locales');
72 }
73
74 /**
75 * {@inheritdoc}
76 */
77 public function beforeCreateStub(StubbingContextInterface $context)
78 {
79 return array(
80 'Locales' => Intl::getLocaleBundle()->getLocaleNames('en'),
81 );
82 }
83
84 /**
85 * {@inheritdoc}
86 */
87 public function afterCreateStub(StubbingContextInterface $context)
88 {
89 }
90
91 private function scanLocales(CompilationContextInterface $context)
92 {
93 $tempDir = sys_get_temp_dir() . '/icu-data-locales-source';
94
95 $context->getFilesystem()->remove($tempDir);
96 $context->getFilesystem()->mkdir($tempDir);
97
98 // Temporarily generate the resource bundles
99 $context->getCompiler()->compile($context->getSourceDir() . '/locales', $tempDir);
100
101 // Discover the list of supported locales, which are the names of the resource
102 // bundles in the "locales" directory
103 $locales = glob($tempDir . '/*.res');
104
105 // Remove file extension and sort
106 array_walk($locales, function (&$locale) { $locale = basename($locale, '.res'); });
107 sort($locales);
108
109 // Delete unneeded locales
110 foreach ($locales as $key => $locale) {
111 // Delete all aliases from the list
112 // i.e., "az_AZ" is an alias for "az_Latn_AZ"
113 $content = file_get_contents($context->getSourceDir() . '/locales/' . $locale . '.txt');
114
115 // The key "%%ALIAS" is not accessible through the \ResourceBundle class,
116 // so look in the original .txt file instead
117 if (strpos($content, '%%ALIAS') !== false) {
118 unset($locales[$key]);
119 }
120
121 // Delete locales that have no content (i.e. only "Version" key)
122 $bundle = new \ResourceBundle($locale, $tempDir);
123
124 if (null === $bundle) {
125 throw new RuntimeException('The resource bundle for locale ' . $locale . ' could not be loaded from directory ' . $tempDir);
126 }
127
128 // There seems to be no other way for identifying all keys in this specific
129 // resource bundle
130 if (array_keys(iterator_to_array($bundle)) === array('Version')) {
131 unset($locales[$key]);
132 }
133 }
134
135 $context->getFilesystem()->remove($tempDir);
136
137 return $locales;
138 }
139
140 private function generateTextFiles($targetDirectory, array $locales)
141 {
142 $displayLocales = array_unique(array_merge(
143 $this->languageBundle->getLocales(),
144 $this->regionBundle->getLocales()
145 ));
146
147 $txtWriter = new TextBundleWriter();
148
149 // Generate a list of locale names in the language of each display locale
150 // Each locale name has the form: "Language (Script, Region, Variant1, ...)
151 // Script, Region and Variants are optional. If none of them is available,
152 // the braces are not printed.
153 foreach ($displayLocales as $displayLocale) {
154 // Don't include ICU's root resource bundle
155 if ('root' === $displayLocale) {
156 continue;
157 }
158
159 $names = array();
160
161 foreach ($locales as $locale) {
162 // Don't include ICU's root resource bundle
163 if ($locale === 'root') {
164 continue;
165 }
166
167 if (null !== ($name = $this->generateLocaleName($locale, $displayLocale))) {
168 $names[$locale] = $name;
169 }
170 }
171
172 // If no names could be generated for the current locale, skip it
173 if (0 === count($names)) {
174 continue;
175 }
176
177 $txtWriter->write($targetDirectory, $displayLocale, array('Locales' => $names));
178 }
179 }
180
181 private function generateLocaleName($locale, $displayLocale)
182 {
183 $name = null;
184
185 $lang = \Locale::getPrimaryLanguage($locale);
186 $script = \Locale::getScript($locale);
187 $region = \Locale::getRegion($locale);
188 $variants = \Locale::getAllVariants($locale);
189
190 // Currently the only available variant is POSIX, which we don't want
191 // to include in the list
192 if (count($variants) > 0) {
193 return null;
194 }
195
196 // Some languages are translated together with their region,
197 // i.e. "en_GB" is translated as "British English"
198 // we don't include these languages though because they mess up
199 // the name sorting
200 // $name = $this->langBundle->getLanguageName($displayLocale, $lang, $region);
201
202 // Some languages are simply not translated
203 // Example: "az" (Azerbaijani) has no translation in "af" (Afrikaans)
204 if (null === ($name = $this->languageBundle->getLanguageName($lang, null, $displayLocale))) {
205 return null;
206 }
207
208 // "as" (Assamese) has no "Variants" block
209 //if (!$langBundle->get('Variants')) {
210 // continue;
211 //}
212
213 $extras = array();
214
215 // Discover the name of the script part of the locale
216 // i.e. in zh_Hans_MO, "Hans" is the script
217 if ($script) {
218 // Some scripts are not translated into every language
219 if (null === ($scriptName = $this->languageBundle->getScriptName($script, $lang, $displayLocale))) {
220 return null;
221 }
222
223 $extras[] = $scriptName;
224 }
225
226 // Discover the name of the region part of the locale
227 // i.e. in de_AT, "AT" is the region
228 if ($region) {
229 // Some regions are not translated into every language
230 if (null === ($regionName = $this->regionBundle->getCountryName($region, $displayLocale))) {
231 return null;
232 }
233
234 $extras[] = $regionName;
235 }
236
237 if (count($extras) > 0) {
238 // Remove any existing extras
239 // For example, in German, zh_Hans is "Chinesisch (vereinfacht)".
240 // The latter is the script part which is already included in the
241 // extras and will be appended again with the other extras.
242 if (preg_match('/^(.+)\s+\([^\)]+\)$/', $name, $matches)) {
243 $name = $matches[1];
244 }
245
246 $name .= ' ('.implode(', ', $extras).')';
247 }
248
249 return $name;
250 }
251}