Vous êtes connecté en tant que anonymous Se Deconnecter
Browse code

Application modulaire fonctionnelle !

Emmanuel ROY authored on 12/08/2019 15:10:25
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,510 +0,0 @@
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
-
12
-namespace Symfony\Component\Translation;
13
-
14
-use Symfony\Component\Config\ConfigCacheFactory;
15
-use Symfony\Component\Config\ConfigCacheFactoryInterface;
16
-use Symfony\Component\Config\ConfigCacheInterface;
17
-use Symfony\Component\Translation\Exception\InvalidArgumentException;
18
-use Symfony\Component\Translation\Exception\LogicException;
19
-use Symfony\Component\Translation\Exception\NotFoundResourceException;
20
-use Symfony\Component\Translation\Exception\RuntimeException;
21
-use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
22
-use Symfony\Component\Translation\Formatter\IntlFormatterInterface;
23
-use Symfony\Component\Translation\Formatter\MessageFormatter;
24
-use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
25
-use Symfony\Component\Translation\Loader\LoaderInterface;
26
-use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
27
-use Symfony\Contracts\Translation\TranslatorInterface;
28
-
29
-/**
30
- * @author Fabien Potencier <fabien@symfony.com>
31
- */
32
-class Translator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface
33
-{
34
-    /**
35
-     * @var MessageCatalogueInterface[]
36
-     */
37
-    protected $catalogues = [];
38
-
39
-    /**
40
-     * @var string
41
-     */
42
-    private $locale;
43
-
44
-    /**
45
-     * @var array
46
-     */
47
-    private $fallbackLocales = [];
48
-
49
-    /**
50
-     * @var LoaderInterface[]
51
-     */
52
-    private $loaders = [];
53
-
54
-    /**
55
-     * @var array
56
-     */
57
-    private $resources = [];
58
-
59
-    /**
60
-     * @var MessageFormatterInterface
61
-     */
62
-    private $formatter;
63
-
64
-    /**
65
-     * @var string
66
-     */
67
-    private $cacheDir;
68
-
69
-    /**
70
-     * @var bool
71
-     */
72
-    private $debug;
73
-
74
-    /**
75
-     * @var ConfigCacheFactoryInterface|null
76
-     */
77
-    private $configCacheFactory;
78
-
79
-    /**
80
-     * @var array|null
81
-     */
82
-    private $parentLocales;
83
-
84
-    private $hasIntlFormatter;
85
-
86
-    /**
87
-     * @throws InvalidArgumentException If a locale contains invalid characters
88
-     */
89
-    public function __construct(?string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false)
90
-    {
91
-        $this->setLocale($locale);
92
-
93
-        if (null === $formatter) {
94
-            $formatter = new MessageFormatter();
95
-        }
96
-
97
-        $this->formatter = $formatter;
98
-        $this->cacheDir = $cacheDir;
99
-        $this->debug = $debug;
100
-        $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface;
101
-    }
102
-
103
-    public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
104
-    {
105
-        $this->configCacheFactory = $configCacheFactory;
106
-    }
107
-
108
-    /**
109
-     * Adds a Loader.
110
-     *
111
-     * @param string          $format The name of the loader (@see addResource())
112
-     * @param LoaderInterface $loader A LoaderInterface instance
113
-     */
114
-    public function addLoader($format, LoaderInterface $loader)
115
-    {
116
-        $this->loaders[$format] = $loader;
117
-    }
118
-
119
-    /**
120
-     * Adds a Resource.
121
-     *
122
-     * @param string $format   The name of the loader (@see addLoader())
123
-     * @param mixed  $resource The resource name
124
-     * @param string $locale   The locale
125
-     * @param string $domain   The domain
126
-     *
127
-     * @throws InvalidArgumentException If the locale contains invalid characters
128
-     */
129
-    public function addResource($format, $resource, $locale, $domain = null)
130
-    {
131
-        if (null === $domain) {
132
-            $domain = 'messages';
133
-        }
134
-
135
-        $this->assertValidLocale($locale);
136
-
137
-        $this->resources[$locale][] = [$format, $resource, $domain];
138
-
139
-        if (\in_array($locale, $this->fallbackLocales)) {
140
-            $this->catalogues = [];
141
-        } else {
142
-            unset($this->catalogues[$locale]);
143
-        }
144
-    }
145
-
146
-    /**
147
-     * {@inheritdoc}
148
-     */
149
-    public function setLocale($locale)
150
-    {
151
-        $this->assertValidLocale($locale);
152
-        $this->locale = $locale;
153
-    }
154
-
155
-    /**
156
-     * {@inheritdoc}
157
-     */
158
-    public function getLocale()
159
-    {
160
-        return $this->locale;
161
-    }
162
-
163
-    /**
164
-     * Sets the fallback locales.
165
-     *
166
-     * @param array $locales The fallback locales
167
-     *
168
-     * @throws InvalidArgumentException If a locale contains invalid characters
169
-     */
170
-    public function setFallbackLocales(array $locales)
171
-    {
172
-        // needed as the fallback locales are linked to the already loaded catalogues
173
-        $this->catalogues = [];
174
-
175
-        foreach ($locales as $locale) {
176
-            $this->assertValidLocale($locale);
177
-        }
178
-
179
-        $this->fallbackLocales = $locales;
180
-    }
181
-
182
-    /**
183
-     * Gets the fallback locales.
184
-     *
185
-     * @internal since Symfony 4.2
186
-     *
187
-     * @return array The fallback locales
188
-     */
189
-    public function getFallbackLocales()
190
-    {
191
-        return $this->fallbackLocales;
192
-    }
193
-
194
-    /**
195
-     * {@inheritdoc}
196
-     */
197
-    public function trans($id, array $parameters = [], $domain = null, $locale = null)
198
-    {
199
-        if (null === $domain) {
200
-            $domain = 'messages';
201
-        }
202
-
203
-        $id = (string) $id;
204
-        $catalogue = $this->getCatalogue($locale);
205
-        $locale = $catalogue->getLocale();
206
-        while (!$catalogue->defines($id, $domain)) {
207
-            if ($cat = $catalogue->getFallbackCatalogue()) {
208
-                $catalogue = $cat;
209
-                $locale = $catalogue->getLocale();
210
-            } else {
211
-                break;
212
-            }
213
-        }
214
-
215
-        if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
216
-            return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
217
-        }
218
-
219
-        return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
220
-    }
221
-
222
-    /**
223
-     * {@inheritdoc}
224
-     *
225
-     * @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
226
-     */
227
-    public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null)
228
-    {
229
-        @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%%count%%" parameter.', __METHOD__), E_USER_DEPRECATED);
230
-
231
-        if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
232
-            throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', \get_class($this->formatter)));
233
-        }
234
-
235
-        if (null === $domain) {
236
-            $domain = 'messages';
237
-        }
238
-
239
-        $id = (string) $id;
240
-        $catalogue = $this->getCatalogue($locale);
241
-        $locale = $catalogue->getLocale();
242
-        while (!$catalogue->defines($id, $domain)) {
243
-            if ($cat = $catalogue->getFallbackCatalogue()) {
244
-                $catalogue = $cat;
245
-                $locale = $catalogue->getLocale();
246
-            } else {
247
-                break;
248
-            }
249
-        }
250
-
251
-        if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
252
-            return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, ['%count%' => $number] + $parameters);
253
-        }
254
-
255
-        return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters);
256
-    }
257
-
258
-    /**
259
-     * {@inheritdoc}
260
-     */
261
-    public function getCatalogue($locale = null)
262
-    {
263
-        if (null === $locale) {
264
-            $locale = $this->getLocale();
265
-        } else {
266
-            $this->assertValidLocale($locale);
267
-        }
268
-
269
-        if (!isset($this->catalogues[$locale])) {
270
-            $this->loadCatalogue($locale);
271
-        }
272
-
273
-        return $this->catalogues[$locale];
274
-    }
275
-
276
-    /**
277
-     * Gets the loaders.
278
-     *
279
-     * @return array LoaderInterface[]
280
-     */
281
-    protected function getLoaders()
282
-    {
283
-        return $this->loaders;
284
-    }
285
-
286
-    /**
287
-     * @param string $locale
288
-     */
289
-    protected function loadCatalogue($locale)
290
-    {
291
-        if (null === $this->cacheDir) {
292
-            $this->initializeCatalogue($locale);
293
-        } else {
294
-            $this->initializeCacheCatalogue($locale);
295
-        }
296
-    }
297
-
298
-    /**
299
-     * @param string $locale
300
-     */
301
-    protected function initializeCatalogue($locale)
302
-    {
303
-        $this->assertValidLocale($locale);
304
-
305
-        try {
306
-            $this->doLoadCatalogue($locale);
307
-        } catch (NotFoundResourceException $e) {
308
-            if (!$this->computeFallbackLocales($locale)) {
309
-                throw $e;
310
-            }
311
-        }
312
-        $this->loadFallbackCatalogues($locale);
313
-    }
314
-
315
-    private function initializeCacheCatalogue(string $locale): void
316
-    {
317
-        if (isset($this->catalogues[$locale])) {
318
-            /* Catalogue already initialized. */
319
-            return;
320
-        }
321
-
322
-        $this->assertValidLocale($locale);
323
-        $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale),
324
-            function (ConfigCacheInterface $cache) use ($locale) {
325
-                $this->dumpCatalogue($locale, $cache);
326
-            }
327
-        );
328
-
329
-        if (isset($this->catalogues[$locale])) {
330
-            /* Catalogue has been initialized as it was written out to cache. */
331
-            return;
332
-        }
333
-
334
-        /* Read catalogue from cache. */
335
-        $this->catalogues[$locale] = include $cache->getPath();
336
-    }
337
-
338
-    private function dumpCatalogue($locale, ConfigCacheInterface $cache): void
339
-    {
340
-        $this->initializeCatalogue($locale);
341
-        $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
342
-
343
-        $content = sprintf(<<<EOF
344
-<?php
345
-
346
-use Symfony\Component\Translation\MessageCatalogue;
347
-
348
-\$catalogue = new MessageCatalogue('%s', %s);
349
-
350
-%s
351
-return \$catalogue;
352
-
353
-EOF
354
-            ,
355
-            $locale,
356
-            var_export($this->getAllMessages($this->catalogues[$locale]), true),
357
-            $fallbackContent
358
-        );
359
-
360
-        $cache->write($content, $this->catalogues[$locale]->getResources());
361
-    }
362
-
363
-    private function getFallbackContent(MessageCatalogue $catalogue): string
364
-    {
365
-        $fallbackContent = '';
366
-        $current = '';
367
-        $replacementPattern = '/[^a-z0-9_]/i';
368
-        $fallbackCatalogue = $catalogue->getFallbackCatalogue();
369
-        while ($fallbackCatalogue) {
370
-            $fallback = $fallbackCatalogue->getLocale();
371
-            $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
372
-            $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));
373
-
374
-            $fallbackContent .= sprintf(<<<'EOF'
375
-$catalogue%s = new MessageCatalogue('%s', %s);
376
-$catalogue%s->addFallbackCatalogue($catalogue%s);
377
-
378
-EOF
379
-                ,
380
-                $fallbackSuffix,
381
-                $fallback,
382
-                var_export($this->getAllMessages($fallbackCatalogue), true),
383
-                $currentSuffix,
384
-                $fallbackSuffix
385
-            );
386
-            $current = $fallbackCatalogue->getLocale();
387
-            $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
388
-        }
389
-
390
-        return $fallbackContent;
391
-    }
392
-
393
-    private function getCatalogueCachePath($locale)
394
-    {
395
-        return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->fallbackLocales), true)), 0, 7), '/', '_').'.php';
396
-    }
397
-
398
-    /**
399
-     * @internal
400
-     */
401
-    protected function doLoadCatalogue($locale): void
402
-    {
403
-        $this->catalogues[$locale] = new MessageCatalogue($locale);
404
-
405
-        if (isset($this->resources[$locale])) {
406
-            foreach ($this->resources[$locale] as $resource) {
407
-                if (!isset($this->loaders[$resource[0]])) {
408
-                    throw new RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0]));
409
-                }
410
-                $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
411
-            }
412
-        }
413
-    }
414
-
415
-    private function loadFallbackCatalogues($locale): void
416
-    {
417
-        $current = $this->catalogues[$locale];
418
-
419
-        foreach ($this->computeFallbackLocales($locale) as $fallback) {
420
-            if (!isset($this->catalogues[$fallback])) {
421
-                $this->initializeCatalogue($fallback);
422
-            }
423
-
424
-            $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
425
-            foreach ($this->catalogues[$fallback]->getResources() as $resource) {
426
-                $fallbackCatalogue->addResource($resource);
427
-            }
428
-            $current->addFallbackCatalogue($fallbackCatalogue);
429
-            $current = $fallbackCatalogue;
430
-        }
431
-    }
432
-
433
-    protected function computeFallbackLocales($locale)
434
-    {
435
-        if (null === $this->parentLocales) {
436
-            $parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true);
437
-        }
438
-
439
-        $locales = [];
440
-        foreach ($this->fallbackLocales as $fallback) {
441
-            if ($fallback === $locale) {
442
-                continue;
443
-            }
444
-
445
-            $locales[] = $fallback;
446
-        }
447
-
448
-        while ($locale) {
449
-            $parent = $parentLocales[$locale] ?? null;
450
-
451
-            if (!$parent && false !== strrchr($locale, '_')) {
452
-                $locale = substr($locale, 0, -\strlen(strrchr($locale, '_')));
453
-            } elseif ('root' !== $parent) {
454
-                $locale = $parent;
455
-            } else {
456
-                $locale = null;
457
-            }
458
-
459
-            if (null !== $locale) {
460
-                array_unshift($locales, $locale);
461
-            }
462
-        }
463
-
464
-        return array_unique($locales);
465
-    }
466
-
467
-    /**
468
-     * Asserts that the locale is valid, throws an Exception if not.
469
-     *
470
-     * @param string $locale Locale to tests
471
-     *
472
-     * @throws InvalidArgumentException If the locale contains invalid characters
473
-     */
474
-    protected function assertValidLocale($locale)
475
-    {
476
-        if (1 !== preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
477
-            throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
478
-        }
479
-    }
480
-
481
-    /**
482
-     * Provides the ConfigCache factory implementation, falling back to a
483
-     * default implementation if necessary.
484
-     */
485
-    private function getConfigCacheFactory(): ConfigCacheFactoryInterface
486
-    {
487
-        if (!$this->configCacheFactory) {
488
-            $this->configCacheFactory = new ConfigCacheFactory($this->debug);
489
-        }
490
-
491
-        return $this->configCacheFactory;
492
-    }
493
-
494
-    private function getAllMessages(MessageCatalogueInterface $catalogue): array
495
-    {
496
-        $allMessages = [];
497
-
498
-        foreach ($catalogue->all() as $domain => $messages) {
499
-            if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
500
-                $allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages;
501
-                $messages = array_diff_key($messages, $intlMessages);
502
-            }
503
-            if ($messages) {
504
-                $allMessages[$domain] = $messages;
505
-            }
506
-        }
507
-
508
-        return $allMessages;
509
-    }
510
-}
Browse code

initial commit

Emmanuel ROY authored on 09/08/2019 08:39:02
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,510 @@
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
+
12
+namespace Symfony\Component\Translation;
13
+
14
+use Symfony\Component\Config\ConfigCacheFactory;
15
+use Symfony\Component\Config\ConfigCacheFactoryInterface;
16
+use Symfony\Component\Config\ConfigCacheInterface;
17
+use Symfony\Component\Translation\Exception\InvalidArgumentException;
18
+use Symfony\Component\Translation\Exception\LogicException;
19
+use Symfony\Component\Translation\Exception\NotFoundResourceException;
20
+use Symfony\Component\Translation\Exception\RuntimeException;
21
+use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface;
22
+use Symfony\Component\Translation\Formatter\IntlFormatterInterface;
23
+use Symfony\Component\Translation\Formatter\MessageFormatter;
24
+use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
25
+use Symfony\Component\Translation\Loader\LoaderInterface;
26
+use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
27
+use Symfony\Contracts\Translation\TranslatorInterface;
28
+
29
+/**
30
+ * @author Fabien Potencier <fabien@symfony.com>
31
+ */
32
+class Translator implements LegacyTranslatorInterface, TranslatorInterface, TranslatorBagInterface
33
+{
34
+    /**
35
+     * @var MessageCatalogueInterface[]
36
+     */
37
+    protected $catalogues = [];
38
+
39
+    /**
40
+     * @var string
41
+     */
42
+    private $locale;
43
+
44
+    /**
45
+     * @var array
46
+     */
47
+    private $fallbackLocales = [];
48
+
49
+    /**
50
+     * @var LoaderInterface[]
51
+     */
52
+    private $loaders = [];
53
+
54
+    /**
55
+     * @var array
56
+     */
57
+    private $resources = [];
58
+
59
+    /**
60
+     * @var MessageFormatterInterface
61
+     */
62
+    private $formatter;
63
+
64
+    /**
65
+     * @var string
66
+     */
67
+    private $cacheDir;
68
+
69
+    /**
70
+     * @var bool
71
+     */
72
+    private $debug;
73
+
74
+    /**
75
+     * @var ConfigCacheFactoryInterface|null
76
+     */
77
+    private $configCacheFactory;
78
+
79
+    /**
80
+     * @var array|null
81
+     */
82
+    private $parentLocales;
83
+
84
+    private $hasIntlFormatter;
85
+
86
+    /**
87
+     * @throws InvalidArgumentException If a locale contains invalid characters
88
+     */
89
+    public function __construct(?string $locale, MessageFormatterInterface $formatter = null, string $cacheDir = null, bool $debug = false)
90
+    {
91
+        $this->setLocale($locale);
92
+
93
+        if (null === $formatter) {
94
+            $formatter = new MessageFormatter();
95
+        }
96
+
97
+        $this->formatter = $formatter;
98
+        $this->cacheDir = $cacheDir;
99
+        $this->debug = $debug;
100
+        $this->hasIntlFormatter = $formatter instanceof IntlFormatterInterface;
101
+    }
102
+
103
+    public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
104
+    {
105
+        $this->configCacheFactory = $configCacheFactory;
106
+    }
107
+
108
+    /**
109
+     * Adds a Loader.
110
+     *
111
+     * @param string          $format The name of the loader (@see addResource())
112
+     * @param LoaderInterface $loader A LoaderInterface instance
113
+     */
114
+    public function addLoader($format, LoaderInterface $loader)
115
+    {
116
+        $this->loaders[$format] = $loader;
117
+    }
118
+
119
+    /**
120
+     * Adds a Resource.
121
+     *
122
+     * @param string $format   The name of the loader (@see addLoader())
123
+     * @param mixed  $resource The resource name
124
+     * @param string $locale   The locale
125
+     * @param string $domain   The domain
126
+     *
127
+     * @throws InvalidArgumentException If the locale contains invalid characters
128
+     */
129
+    public function addResource($format, $resource, $locale, $domain = null)
130
+    {
131
+        if (null === $domain) {
132
+            $domain = 'messages';
133
+        }
134
+
135
+        $this->assertValidLocale($locale);
136
+
137
+        $this->resources[$locale][] = [$format, $resource, $domain];
138
+
139
+        if (\in_array($locale, $this->fallbackLocales)) {
140
+            $this->catalogues = [];
141
+        } else {
142
+            unset($this->catalogues[$locale]);
143
+        }
144
+    }
145
+
146
+    /**
147
+     * {@inheritdoc}
148
+     */
149
+    public function setLocale($locale)
150
+    {
151
+        $this->assertValidLocale($locale);
152
+        $this->locale = $locale;
153
+    }
154
+
155
+    /**
156
+     * {@inheritdoc}
157
+     */
158
+    public function getLocale()
159
+    {
160
+        return $this->locale;
161
+    }
162
+
163
+    /**
164
+     * Sets the fallback locales.
165
+     *
166
+     * @param array $locales The fallback locales
167
+     *
168
+     * @throws InvalidArgumentException If a locale contains invalid characters
169
+     */
170
+    public function setFallbackLocales(array $locales)
171
+    {
172
+        // needed as the fallback locales are linked to the already loaded catalogues
173
+        $this->catalogues = [];
174
+
175
+        foreach ($locales as $locale) {
176
+            $this->assertValidLocale($locale);
177
+        }
178
+
179
+        $this->fallbackLocales = $locales;
180
+    }
181
+
182
+    /**
183
+     * Gets the fallback locales.
184
+     *
185
+     * @internal since Symfony 4.2
186
+     *
187
+     * @return array The fallback locales
188
+     */
189
+    public function getFallbackLocales()
190
+    {
191
+        return $this->fallbackLocales;
192
+    }
193
+
194
+    /**
195
+     * {@inheritdoc}
196
+     */
197
+    public function trans($id, array $parameters = [], $domain = null, $locale = null)
198
+    {
199
+        if (null === $domain) {
200
+            $domain = 'messages';
201
+        }
202
+
203
+        $id = (string) $id;
204
+        $catalogue = $this->getCatalogue($locale);
205
+        $locale = $catalogue->getLocale();
206
+        while (!$catalogue->defines($id, $domain)) {
207
+            if ($cat = $catalogue->getFallbackCatalogue()) {
208
+                $catalogue = $cat;
209
+                $locale = $catalogue->getLocale();
210
+            } else {
211
+                break;
212
+            }
213
+        }
214
+
215
+        if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
216
+            return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
217
+        }
218
+
219
+        return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
220
+    }
221
+
222
+    /**
223
+     * {@inheritdoc}
224
+     *
225
+     * @deprecated since Symfony 4.2, use the trans() method instead with a %count% parameter
226
+     */
227
+    public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null)
228
+    {
229
+        @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use the trans() one instead with a "%%count%%" parameter.', __METHOD__), E_USER_DEPRECATED);
230
+
231
+        if (!$this->formatter instanceof ChoiceMessageFormatterInterface) {
232
+            throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', \get_class($this->formatter)));
233
+        }
234
+
235
+        if (null === $domain) {
236
+            $domain = 'messages';
237
+        }
238
+
239
+        $id = (string) $id;
240
+        $catalogue = $this->getCatalogue($locale);
241
+        $locale = $catalogue->getLocale();
242
+        while (!$catalogue->defines($id, $domain)) {
243
+            if ($cat = $catalogue->getFallbackCatalogue()) {
244
+                $catalogue = $cat;
245
+                $locale = $catalogue->getLocale();
246
+            } else {
247
+                break;
248
+            }
249
+        }
250
+
251
+        if ($this->hasIntlFormatter && $catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
252
+            return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, ['%count%' => $number] + $parameters);
253
+        }
254
+
255
+        return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters);
256
+    }
257
+
258
+    /**
259
+     * {@inheritdoc}
260
+     */
261
+    public function getCatalogue($locale = null)
262
+    {
263
+        if (null === $locale) {
264
+            $locale = $this->getLocale();
265
+        } else {
266
+            $this->assertValidLocale($locale);
267
+        }
268
+
269
+        if (!isset($this->catalogues[$locale])) {
270
+            $this->loadCatalogue($locale);
271
+        }
272
+
273
+        return $this->catalogues[$locale];
274
+    }
275
+
276
+    /**
277
+     * Gets the loaders.
278
+     *
279
+     * @return array LoaderInterface[]
280
+     */
281
+    protected function getLoaders()
282
+    {
283
+        return $this->loaders;
284
+    }
285
+
286
+    /**
287
+     * @param string $locale
288
+     */
289
+    protected function loadCatalogue($locale)
290
+    {
291
+        if (null === $this->cacheDir) {
292
+            $this->initializeCatalogue($locale);
293
+        } else {
294
+            $this->initializeCacheCatalogue($locale);
295
+        }
296
+    }
297
+
298
+    /**
299
+     * @param string $locale
300
+     */
301
+    protected function initializeCatalogue($locale)
302
+    {
303
+        $this->assertValidLocale($locale);
304
+
305
+        try {
306
+            $this->doLoadCatalogue($locale);
307
+        } catch (NotFoundResourceException $e) {
308
+            if (!$this->computeFallbackLocales($locale)) {
309
+                throw $e;
310
+            }
311
+        }
312
+        $this->loadFallbackCatalogues($locale);
313
+    }
314
+
315
+    private function initializeCacheCatalogue(string $locale): void
316
+    {
317
+        if (isset($this->catalogues[$locale])) {
318
+            /* Catalogue already initialized. */
319
+            return;
320
+        }
321
+
322
+        $this->assertValidLocale($locale);
323
+        $cache = $this->getConfigCacheFactory()->cache($this->getCatalogueCachePath($locale),
324
+            function (ConfigCacheInterface $cache) use ($locale) {
325
+                $this->dumpCatalogue($locale, $cache);
326
+            }
327
+        );
328
+
329
+        if (isset($this->catalogues[$locale])) {
330
+            /* Catalogue has been initialized as it was written out to cache. */
331
+            return;
332
+        }
333
+
334
+        /* Read catalogue from cache. */
335
+        $this->catalogues[$locale] = include $cache->getPath();
336
+    }
337
+
338
+    private function dumpCatalogue($locale, ConfigCacheInterface $cache): void
339
+    {
340
+        $this->initializeCatalogue($locale);
341
+        $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]);
342
+
343
+        $content = sprintf(<<<EOF
344
+<?php
345
+
346
+use Symfony\Component\Translation\MessageCatalogue;
347
+
348
+\$catalogue = new MessageCatalogue('%s', %s);
349
+
350
+%s
351
+return \$catalogue;
352
+
353
+EOF
354
+            ,
355
+            $locale,
356
+            var_export($this->getAllMessages($this->catalogues[$locale]), true),
357
+            $fallbackContent
358
+        );
359
+
360
+        $cache->write($content, $this->catalogues[$locale]->getResources());
361
+    }
362
+
363
+    private function getFallbackContent(MessageCatalogue $catalogue): string
364
+    {
365
+        $fallbackContent = '';
366
+        $current = '';
367
+        $replacementPattern = '/[^a-z0-9_]/i';
368
+        $fallbackCatalogue = $catalogue->getFallbackCatalogue();
369
+        while ($fallbackCatalogue) {
370
+            $fallback = $fallbackCatalogue->getLocale();
371
+            $fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
372
+            $currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));
373
+
374
+            $fallbackContent .= sprintf(<<<'EOF'
375
+$catalogue%s = new MessageCatalogue('%s', %s);
376
+$catalogue%s->addFallbackCatalogue($catalogue%s);
377
+
378
+EOF
379
+                ,
380
+                $fallbackSuffix,
381
+                $fallback,
382
+                var_export($this->getAllMessages($fallbackCatalogue), true),
383
+                $currentSuffix,
384
+                $fallbackSuffix
385
+            );
386
+            $current = $fallbackCatalogue->getLocale();
387
+            $fallbackCatalogue = $fallbackCatalogue->getFallbackCatalogue();
388
+        }
389
+
390
+        return $fallbackContent;
391
+    }
392
+
393
+    private function getCatalogueCachePath($locale)
394
+    {
395
+        return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->fallbackLocales), true)), 0, 7), '/', '_').'.php';
396
+    }
397
+
398
+    /**
399
+     * @internal
400
+     */
401
+    protected function doLoadCatalogue($locale): void
402
+    {
403
+        $this->catalogues[$locale] = new MessageCatalogue($locale);
404
+
405
+        if (isset($this->resources[$locale])) {
406
+            foreach ($this->resources[$locale] as $resource) {
407
+                if (!isset($this->loaders[$resource[0]])) {
408
+                    throw new RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0]));
409
+                }
410
+                $this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
411
+            }
412
+        }
413
+    }
414
+
415
+    private function loadFallbackCatalogues($locale): void
416
+    {
417
+        $current = $this->catalogues[$locale];
418
+
419
+        foreach ($this->computeFallbackLocales($locale) as $fallback) {
420
+            if (!isset($this->catalogues[$fallback])) {
421
+                $this->initializeCatalogue($fallback);
422
+            }
423
+
424
+            $fallbackCatalogue = new MessageCatalogue($fallback, $this->getAllMessages($this->catalogues[$fallback]));
425
+            foreach ($this->catalogues[$fallback]->getResources() as $resource) {
426
+                $fallbackCatalogue->addResource($resource);
427
+            }
428
+            $current->addFallbackCatalogue($fallbackCatalogue);
429
+            $current = $fallbackCatalogue;
430
+        }
431
+    }
432
+
433
+    protected function computeFallbackLocales($locale)
434
+    {
435
+        if (null === $this->parentLocales) {
436
+            $parentLocales = json_decode(file_get_contents(__DIR__.'/Resources/data/parents.json'), true);
437
+        }
438
+
439
+        $locales = [];
440
+        foreach ($this->fallbackLocales as $fallback) {
441
+            if ($fallback === $locale) {
442
+                continue;
443
+            }
444
+
445
+            $locales[] = $fallback;
446
+        }
447
+
448
+        while ($locale) {
449
+            $parent = $parentLocales[$locale] ?? null;
450
+
451
+            if (!$parent && false !== strrchr($locale, '_')) {
452
+                $locale = substr($locale, 0, -\strlen(strrchr($locale, '_')));
453
+            } elseif ('root' !== $parent) {
454
+                $locale = $parent;
455
+            } else {
456
+                $locale = null;
457
+            }
458
+
459
+            if (null !== $locale) {
460
+                array_unshift($locales, $locale);
461
+            }
462
+        }
463
+
464
+        return array_unique($locales);
465
+    }
466
+
467
+    /**
468
+     * Asserts that the locale is valid, throws an Exception if not.
469
+     *
470
+     * @param string $locale Locale to tests
471
+     *
472
+     * @throws InvalidArgumentException If the locale contains invalid characters
473
+     */
474
+    protected function assertValidLocale($locale)
475
+    {
476
+        if (1 !== preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
477
+            throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
478
+        }
479
+    }
480
+
481
+    /**
482
+     * Provides the ConfigCache factory implementation, falling back to a
483
+     * default implementation if necessary.
484
+     */
485
+    private function getConfigCacheFactory(): ConfigCacheFactoryInterface
486
+    {
487
+        if (!$this->configCacheFactory) {
488
+            $this->configCacheFactory = new ConfigCacheFactory($this->debug);
489
+        }
490
+
491
+        return $this->configCacheFactory;
492
+    }
493
+
494
+    private function getAllMessages(MessageCatalogueInterface $catalogue): array
495
+    {
496
+        $allMessages = [];
497
+
498
+        foreach ($catalogue->all() as $domain => $messages) {
499
+            if ($intlMessages = $catalogue->all($domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
500
+                $allMessages[$domain.MessageCatalogue::INTL_DOMAIN_SUFFIX] = $intlMessages;
501
+                $messages = array_diff_key($messages, $intlMessages);
502
+            }
503
+            if ($messages) {
504
+                $allMessages[$domain] = $messages;
505
+            }
506
+        }
507
+
508
+        return $allMessages;
509
+    }
510
+}