Completed
Push — master ( 7b1c38...0b8436 )
by Craig
09:54 queued 03:22
created

Translator::transChoice()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 5
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula Foundation - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\Common\Translator;
15
16
use InvalidArgumentException;
17
use Psr\Container\ContainerInterface;
18
use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
19
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
20
use Symfony\Component\Translation\Loader\PoFileLoader;
21
use Symfony\Component\Translation\Loader\XliffFileLoader;
22
use Symfony\Component\Translation\Translator as BaseTranslator;
23
use Zikula\Bundle\CoreBundle\Translation\SymfonyLoader\MockPotFileLoader;
24
25
/**
26
 * Translator
27
 */
28
class Translator extends BaseTranslator implements WarmableInterface, TranslatorInterface
29
{
30
    /**
31
     * @var ContainerInterface
32
     */
33
    protected $container;
34
35
    /**
36
     * @var string
37
     */
38
    protected $domain;
39
40
    /**
41
     * @var array
42
     */
43
    protected $loaderIds;
44
45
    /**
46
     * @var array
47
     */
48
    protected $options = [
49
        'cache_dir' => null,
50
        'debug' => false,
51
        'resource_files' => []
52
    ];
53
54
    /**
55
     * @var array
56
     */
57
    private $resourceLocales;
58
59
    /**
60
     * @throws InvalidArgumentException
61
     */
62
    public function __construct(
63
        ContainerInterface $container,
64
        MessageFormatterInterface $formatter = null,
65
        string $defaultLocale = 'en',
66
        array $loaderIds = [],
67
        array $options = []
68
    ) {
69
        $this->container = $container;
70
        $this->loaderIds = $loaderIds;
71
        // check option names
72
        if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
73
            throw new InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff)));
74
        }
75
76
        $this->domain = 'zikula';
77
        $this->options = array_merge($this->options, $options);
78
        $this->resourceLocales = array_keys($this->options['resource_files']);
79
        if (null !== $this->options['cache_dir'] && $this->options['debug']) {
80
            $this->loadResources();
81
        }
82
83
        parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug']);
84
    }
85
86
    /**
87
     * Warms up the cache.
88
     *
89
     * @param string $cacheDir The cache directory
90
     */
91
    public function warmUp($cacheDir): void
92
    {
93
        // skip warmUp when translator doesn't use cache
94
        if (null === $this->options['cache_dir']) {
95
            return;
96
        }
97
        foreach ($this->resourceLocales as $locale) {
98
            $this->loadCatalogue($locale);
99
        }
100
    }
101
102
    /**
103
     * @param string $locale
104
     */
105
    protected function initializeCatalogue($locale): void
106
    {
107
        $this->initialize();
108
        parent::initializeCatalogue($locale);
109
    }
110
111
    /**
112
     * Initialize translator
113
     */
114
    protected function initialize(): void
115
    {
116
        $this->loadResources();
117
118
        // TODO remove again
119
        if (empty($this->loaderIds)) {
120
            $this->loaderIds = [
121
                'dummy' => [
122
                    'po' => PoFileLoader::class,
123
                    'pot' => MockPotFileLoader::class,
124
                    'xlf' => XliffFileLoader::class
125
                ]
126
            ];
127
        }
128
        foreach ($this->loaderIds as $id => $aliases) {
129
            foreach ($aliases as $alias => $loaderClass) {
130
                $this->addLoader($alias, new $loaderClass());
131
            }
132
        }
133
134
//         foreach ($this->loaderIds as $id => $aliases) {
135
//             foreach ($aliases as $alias) {
136
//                 $this->addLoader($alias, $this->container->get($id));
137
//             }
138
//         }
139
    }
140
141
    /**
142
     * Load zikula resource files
143
     */
144
    private function loadResources(): void
145
    {
146
        foreach ($this->options['resource_files'] as $locale => $files) {
147
            foreach ($files as $key => $file) {
148
                $c = mb_substr_count($file, '.');
149
150
                if ($c < 2) {
151
                    // filename is domain.format
152
                    list($domain, $format) = explode('.', basename($file), 2);
153
                } else {
154
                    // filename is domain.locale.format
155
                    list($domain, $locale, $format) = explode('.', basename($file), 3);
156
                }
157
158
                $this->addResource($format, $file, $locale, $domain);
159
                unset($this->options['resource_files'][$locale][$key]);
160
            }
161
        }
162
    }
163
164
    public function setDomain(string $domain = null): void
165
    {
166
        $this->domain = $domain;
167
    }
168
169
    public function getDomain(): string
170
    {
171
        return $this->domain;
172
    }
173
174
    public function trans($id, array $parameters = [], $domain = null, $locale = null)
175
    {
176
        $domain = $domain ?? $this->domain;
177
        $locale = $locale ?? $this->getLocale();
178
179
        return parent::trans($id, $parameters, $domain, $locale);
180
    }
181
182
    public function __(string $msg, string $domain = null, string $locale = null): string
183
    {
184
        return $this->trans($msg, [], $domain, $locale);
185
    }
186
187
    public function _n(string $m1, string $m2, int $number, string $domain = null, string $locale = null): string
188
    {
189
        $message = $this->chooseMessage($m1, $m2, $number, $domain);
190
191
        return $this->trans($message, ['%count%' => $number], $domain, $locale);
192
    }
193
194
    public function __f(string $msg, array $parameters = [], string $domain = null, string $locale = null): string
195
    {
196
        return $this->trans($msg, $parameters, $domain, $locale);
197
    }
198
199
    public function _fn(string $m1, string $m2, int $number, array $parameters = [], string $domain = null, string $locale = null): string
200
    {
201
        $message = $this->chooseMessage($m1, $m2, $number, $domain);
202
203
        return $this->trans($message, ['%count%' => $number] + $parameters, $domain, $locale);
204
    }
205
206
    /**
207
     * Choose message if no translation catalogue.
208
     */
209
    private function chooseMessage(string $m1, string $m2, int $number, string $domain = null): string
210
    {
211
        $message = $m2;
212
        if ('en' === $domain || 'en' === $this->getLocale()) {
213
            $domains = $this->getCatalogue($this->getLocale())->getDomains();
214
            if (!in_array($this->domain, $domains, true)) {
215
                $message = 1 === $number ? $m1 : $m2;
216
            }
217
        }
218
219
        return $message;
220
    }
221
}
222