PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.5
Independent Analytics – WordPress Analytics Plugin v2.15.5
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / symfony / translation / Translator.php
independent-analytics / vendor / symfony / translation Last commit date
Catalogue 1 month ago Command 1 month ago DataCollector 1 month ago DependencyInjection 1 month ago Dumper 1 month ago Exception 1 month ago Extractor 1 month ago Formatter 1 month ago Loader 1 month ago Provider 1 month ago Reader 1 month ago Resources 1 month ago Test 1 month ago Util 1 month ago Writer 1 month ago DataCollectorTranslator.php 1 month ago IdentityTranslator.php 2 years ago LoggingTranslator.php 1 month ago MessageCatalogue.php 1 month ago MessageCatalogueInterface.php 1 month ago MetadataAwareInterface.php 1 month ago PseudoLocalizationTranslator.php 1 month ago TranslatableMessage.php 1 month ago Translator.php 1 month ago TranslatorBag.php 1 month ago TranslatorBagInterface.php 1 month ago
Translator.php
383 lines
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 namespace IAWPSCOPED\Symfony\Component\Translation;
12
13 use IAWPSCOPED\Symfony\Component\Config\ConfigCacheFactory;
14 use IAWPSCOPED\Symfony\Component\Config\ConfigCacheFactoryInterface;
15 use IAWPSCOPED\Symfony\Component\Config\ConfigCacheInterface;
16 use IAWPSCOPED\Symfony\Component\Translation\Exception\InvalidArgumentException;
17 use IAWPSCOPED\Symfony\Component\Translation\Exception\NotFoundResourceException;
18 use IAWPSCOPED\Symfony\Component\Translation\Exception\RuntimeException;
19 use IAWPSCOPED\Symfony\Component\Translation\Formatter\IntlFormatterInterface;
20 use IAWPSCOPED\Symfony\Component\Translation\Formatter\MessageFormatter;
21 use IAWPSCOPED\Symfony\Component\Translation\Formatter\MessageFormatterInterface;
22 use IAWPSCOPED\Symfony\Component\Translation\Loader\LoaderInterface;
23 use IAWPSCOPED\Symfony\Contracts\Translation\LocaleAwareInterface;
24 use IAWPSCOPED\Symfony\Contracts\Translation\TranslatorInterface;
25 // Help opcache.preload discover always-needed symbols
26 \class_exists(MessageCatalogue::class);
27 /**
28 * @author Fabien Potencier <fabien@symfony.com>
29 * @internal
30 */
31 class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleAwareInterface
32 {
33 /**
34 * @var MessageCatalogueInterface[]
35 */
36 protected $catalogues = [];
37 private string $locale;
38 /**
39 * @var string[]
40 */
41 private array $fallbackLocales = [];
42 /**
43 * @var LoaderInterface[]
44 */
45 private array $loaders = [];
46 private array $resources = [];
47 private $formatter;
48 private ?string $cacheDir;
49 private bool $debug;
50 private array $cacheVary;
51 private $configCacheFactory;
52 private array $parentLocales;
53 private bool $hasIntlFormatter;
54 /**
55 * @throws InvalidArgumentException If a locale contains invalid characters
56 */
57 public function __construct(string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = \false, array $cacheVary = [])
58 {
59 $this->setLocale($locale);
60 if (null === $formatter) {
61 $formatter = new MessageFormatter();
62 }
63 $this->formatter = $formatter;
64 $this->cacheDir = $cacheDir;
65 $this->debug = $debug;
66 $this->cacheVary = $cacheVary;
67 $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface;
68 }
69 public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
70 {
71 $this->configCacheFactory = $configCacheFactory;
72 }
73 /**
74 * Adds a Loader.
75 *
76 * @param string $format The name of the loader (@see addResource())
77 */
78 public function addLoader(string $format, LoaderInterface $loader)
79 {
80 $this->loaders[$format] = $loader;
81 }
82 /**
83 * Adds a Resource.
84 *
85 * @param string $format The name of the loader (@see addLoader())
86 * @param mixed $resource The resource name
87 *
88 * @throws InvalidArgumentException If the locale contains invalid characters
89 */
90 public function addResource(string $format, mixed $resource, string $locale, string $domain = null)
91 {
92 if (null === $domain) {
93 $domain = 'messages';
94 }
95 $this->assertValidLocale($locale);
96 $locale ?: ($locale = \class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
97 $this->resources[$locale][] = [$format, $resource, $domain];
98 if (\in_array($locale, $this->fallbackLocales)) {
99 $this->catalogues = [];
100 } else {
101 unset($this->catalogues[$locale]);
102 }
103 }
104 /**
105 * {@inheritdoc}
106 */
107 public function setLocale(string $locale)
108 {
109 $this->assertValidLocale($locale);
110 $this->locale = $locale;
111 }
112 /**
113 * {@inheritdoc}
114 */
115 public function getLocale() : string
116 {
117 return $this->locale ?: (\class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
118 }
119 /**
120 * Sets the fallback locales.
121 *
122 * @param string[] $locales
123 *
124 * @throws InvalidArgumentException If a locale contains invalid characters
125 */
126 public function setFallbackLocales(array $locales)
127 {
128 // needed as the fallback locales are linked to the already loaded catalogues
129 $this->catalogues = [];
130 foreach ($locales as $locale) {
131 $this->assertValidLocale($locale);
132 }
133 $this->fallbackLocales = $this->cacheVary['fallback_locales'] = $locales;
134 }
135 /**
136 * Gets the fallback locales.
137 *
138 * @internal
139 */
140 public function getFallbackLocales() : array
141 {
142 return $this->fallbackLocales;
143 }
144 /**
145 * {@inheritdoc}
146 */
147 public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null) : string
148 {
149 if (null === $id || '' === $id) {
150 return '';
151 }
152 if (null === $domain) {
153 $domain = 'messages';
154 }
155 $catalogue = $this->getCatalogue($locale);
156 $locale = $catalogue->getLocale();
157 while (!$catalogue->defines($id, $domain)) {
158 if ($cat = $catalogue->getFallbackCatalogue()) {
159 $catalogue = $cat;
160 $locale = $catalogue->getLocale();
161 } else {
162 break;
163 }
164 }
165 $len = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX);
166 if ($this->hasIntlFormatter && ($catalogue->defines($id, $domain . MessageCatalogue::INTL_DOMAIN_SUFFIX) || \strlen($domain) > $len && 0 === \substr_compare($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX, -$len, $len))) {
167 return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
168 }
169 return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
170 }
171 /**
172 * {@inheritdoc}
173 */
174 public function getCatalogue(string $locale = null) : MessageCatalogueInterface
175 {
176 if (!$locale) {
177 $locale = $this->getLocale();
178 } else {
179 $this->assertValidLocale($locale);
180 }
181 if (!isset($this->catalogues[$locale])) {
182 $this->loadCatalogue($locale);
183 }
184 return $this->catalogues[$locale];
185 }
186 /**
187 * {@inheritdoc}
188 */
189 public function getCatalogues() : array
190 {
191 return \array_values($this->catalogues);
192 }
193 /**
194 * Gets the loaders.
195 *
196 * @return LoaderInterface[]
197 */
198 protected function getLoaders() : array
199 {
200 return $this->loaders;
201 }
202 protected function loadCatalogue(string $locale)
203 {
204 if (null === $this->cacheDir) {
205 $this->initializeCatalogue($locale);
206 } else {
207 $this->initializeCacheCatalogue($locale);
208 }
209 }
210 protected function initializeCatalogue(string $locale)
211 {
212 $this->assertValidLocale($locale);
213 try {
214 $this->doLoadCatalogue($locale);
215 } catch (NotFoundResourceException $e) {
216 if (!$this->computeFallbackLocales($locale)) {
217 throw $e;
218 }
219 }
220 $this->loadFallbackCatalogues($locale);
221 }
222 private function initializeCacheCatalogue(string $locale) : void
223 {
224 if (isset($this->catalogues[$locale])) {
225 /* Catalogue already initialized. */
226 return;
227 }
228 $this->assertValidLocale($locale);
229 $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale), function (ConfigCacheInterface $cache) use($locale) {
230 $this->dumpCatalogue($locale, $cache);
231 });
232 if (isset($this->catalogues[$locale])) {
233 /* Catalogue has been initialized as it was written out to cache. */
234 return;
235 }
236 /* Read catalogue from cache. */
237 $this->catalogues[$locale] = (include $cache->getPath());
238 }
239 private function dumpCatalogue(string $locale, ConfigCacheInterface $cache) : void
240 {
241 $this->initializeCatalogue($locale);
242 $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
243 $content = \sprintf(<<<EOF
244 <?php
245
246 use Symfony\\Component\\Translation\\MessageCatalogue;
247
248 \$catalogue = new MessageCatalogue('%s', %s);
249
250 %s
251 return \$catalogue;
252
253 EOF
254 , $locale, \var_export($this->getAllMessages($this->catalogues[$locale]), \true), $fallbackContent);
255 $cache->write($content, $this->catalogues[$locale]->getResources());
256 }
257 private function getFallbackContent(MessageCatalogue $catalogue) : string
258 {
259 $fallbackContent = '';
260 $current = '';
261 $replacementPattern = '/[^a-z0-9_]/i';
262 $fallbackCatalogue = $catalogue->getFallbackCatalogue();
263 while ($fallbackCatalogue) {
264 $fallback = $fallbackCatalogue->getLocale();
265 $fallbackSuffix = \ucfirst(\preg_replace($replacementPattern, '_', $fallback));
266 $currentSuffix = \ucfirst(\preg_replace($replacementPattern, '_', $current));
267 $fallbackContent .= \sprintf(<<<'EOF'
268 $catalogue%s = new MessageCatalogue('%s', %s);
269 $catalogue%s->addFallbackCatalogue($catalogue%s);
270
271 EOF
272 , $fallbackSuffix, $fallback, \var_export($this->getAllMessages($fallbackCatalogue), \true), $currentSuffix, $fallbackSuffix);
273 $current = $fallbackCatalogue->getLocale();
274 $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
275 }
276 return $fallbackContent;
277 }
278 private function getCatalogueCachePath(string $locale) : string
279 {
280 return $this->cacheDir . '/catalogue.' . $locale . '.' . \strtr(\substr(\base64_encode(\hash('sha256', \serialize($this->cacheVary), \true)), 0, 7), '/', '_') . '.php';
281 }
282 /**
283 * @internal
284 */
285 protected function doLoadCatalogue(string $locale) : void
286 {
287 $this->catalogues[$locale] = new MessageCatalogue($locale);
288 if (isset($this->resources[$locale])) {
289 foreach ($this->resources[$locale] as $resource) {
290 if (!isset($this->loaders[$resource[0]])) {
291 if (\is_string($resource[1])) {
292 throw new RuntimeException(\sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
293 }
294 throw new RuntimeException(\sprintf('No loader is registered for the "%s" format.', $resource[0]));
295 }
296 $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
297 }
298 }
299 }
300 private function loadFallbackCatalogues(string $locale) : void
301 {
302 $current = $this->catalogues[$locale];
303 foreach ($this->computeFallbackLocales($locale) as $fallback) {
304 if (!isset($this->catalogues[$fallback])) {
305 $this->initializeCatalogue($fallback);
306 }
307 $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
308 foreach ($this->catalogues[$fallback]->getResources() as $resource) {
309 $fallbackCatalogue->addResource($resource);
310 }
311 $current->addFallbackCatalogue($fallbackCatalogue);
312 $current = $fallbackCatalogue;
313 }
314 }
315 protected function computeFallbackLocales(string $locale)
316 {
317 $this->parentLocales ??= \json_decode(\file_get_contents(__DIR__ . '/Resources/data/parents.json'), \true);
318 $originLocale = $locale;
319 $locales = [];
320 while ($locale) {
321 $parent = $this->parentLocales[$locale] ?? null;
322 if ($parent) {
323 $locale = 'root' !== $parent ? $parent : null;
324 } elseif (\function_exists('locale_parse')) {
325 $localeSubTags = \locale_parse($locale);
326 $locale = null;
327 if (1 < \count($localeSubTags)) {
328 \array_pop($localeSubTags);
329 $locale = \locale_compose($localeSubTags) ?: null;
330 }
331 } elseif ($i = \strrpos($locale, '_') ?: \strrpos($locale, '-')) {
332 $locale = \substr($locale, 0, $i);
333 } else {
334 $locale = null;
335 }
336 if (null !== $locale) {
337 $locales[] = $locale;
338 }
339 }
340 foreach ($this->fallbackLocales as $fallback) {
341 if ($fallback === $originLocale) {
342 continue;
343 }
344 $locales[] = $fallback;
345 }
346 return \array_unique($locales);
347 }
348 /**
349 * Asserts that the locale is valid, throws an Exception if not.
350 *
351 * @throws InvalidArgumentException If the locale contains invalid characters
352 */
353 protected function assertValidLocale(string $locale)
354 {
355 if (!\preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
356 throw new InvalidArgumentException(\sprintf('Invalid "%s" locale.', $locale));
357 }
358 }
359 /**
360 * Provides the ConfigCache factory implementation, falling back to a
361 * default implementation if necessary.
362 */
363 private function getConfigCacheFactory() : ConfigCacheFactoryInterface
364 {
365 $this->configCacheFactory ??= new ConfigCacheFactory($this->debug);
366 return $this->configCacheFactory;
367 }
368 private function getAllMessages(MessageCatalogueInterface $catalogue) : array
369 {
370 $allMessages = [];
371 foreach ($catalogue->all() as $domain => $messages) {
372 if ($intlMessages = $catalogue->all($domain . MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
373 $allMessages[$domain . MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages;
374 $messages = \array_diff_key($messages, $intlMessages);
375 }
376 if ($messages) {
377 $allMessages[$domain] = $messages;
378 }
379 }
380 return $allMessages;
381 }
382 }
383