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 / nesbot / carbon / src / Carbon / AbstractTranslator.php
independent-analytics / vendor / nesbot / carbon / src / Carbon Last commit date
Cli 2 years ago Exceptions 1 month ago Lang 2 years ago Laravel 2 years ago List 2 years ago MessageFormatter 2 years ago PHPStan 2 years ago Traits 1 month ago AbstractTranslator.php 1 month ago Carbon.php 2 years ago CarbonConverterInterface.php 2 years ago CarbonImmutable.php 2 years ago CarbonInterface.php 1 month ago CarbonInterval.php 2 years ago CarbonPeriod.php 1 month ago CarbonPeriodImmutable.php 2 years ago CarbonTimeZone.php 1 month ago Factory.php 1 month ago FactoryImmutable.php 2 years ago Language.php 2 years ago Translator.php 2 years ago TranslatorImmutable.php 1 month ago TranslatorStrongTypeInterface.php 2 years ago
AbstractTranslator.php
326 lines
1 <?php
2
3 /**
4 * This file is part of the Carbon package.
5 *
6 * (c) Brian Nesbitt <brian@nesbot.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\Carbon;
12
13 use IAWPSCOPED\Carbon\MessageFormatter\MessageFormatterMapper;
14 use Closure;
15 use ReflectionException;
16 use ReflectionFunction;
17 use IAWPSCOPED\Symfony\Component\Translation;
18 use IAWPSCOPED\Symfony\Component\Translation\Formatter\MessageFormatterInterface;
19 use IAWPSCOPED\Symfony\Component\Translation\Loader\ArrayLoader;
20 /** @internal */
21 abstract class AbstractTranslator extends Translation\Translator
22 {
23 /**
24 * Translator singletons for each language.
25 *
26 * @var array
27 */
28 protected static $singletons = [];
29 /**
30 * List of custom localized messages.
31 *
32 * @var array
33 */
34 protected $messages = [];
35 /**
36 * List of custom directories that contain translation files.
37 *
38 * @var string[]
39 */
40 protected $directories = [];
41 /**
42 * Set to true while constructing.
43 *
44 * @var bool
45 */
46 protected $initializing = \false;
47 /**
48 * List of locales aliases.
49 *
50 * @var array<string, string>
51 */
52 protected $aliases = ['me' => 'sr_Latn_ME', 'scr' => 'sh'];
53 /**
54 * Return a singleton instance of Translator.
55 *
56 * @param string|null $locale optional initial locale ("en" - english by default)
57 *
58 * @return static
59 */
60 public static function get($locale = null)
61 {
62 $locale = $locale ?: 'en';
63 $key = static::class === Translator::class ? $locale : static::class . '|' . $locale;
64 if (!isset(static::$singletons[$key])) {
65 static::$singletons[$key] = new static($locale);
66 }
67 return static::$singletons[$key];
68 }
69 public function __construct($locale, ?MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = \false)
70 {
71 parent::setLocale($locale);
72 $this->initializing = \true;
73 $this->directories = [__DIR__ . '/Lang'];
74 $this->addLoader('array', new ArrayLoader());
75 parent::__construct($locale, new MessageFormatterMapper($formatter), $cacheDir, $debug);
76 $this->initializing = \false;
77 }
78 /**
79 * Returns the list of directories translation files are searched in.
80 *
81 * @return array
82 */
83 public function getDirectories() : array
84 {
85 return $this->directories;
86 }
87 /**
88 * Set list of directories translation files are searched in.
89 *
90 * @param array $directories new directories list
91 *
92 * @return $this
93 */
94 public function setDirectories(array $directories)
95 {
96 $this->directories = $directories;
97 return $this;
98 }
99 /**
100 * Add a directory to the list translation files are searched in.
101 *
102 * @param string $directory new directory
103 *
104 * @return $this
105 */
106 public function addDirectory(string $directory)
107 {
108 $this->directories[] = $directory;
109 return $this;
110 }
111 /**
112 * Remove a directory from the list translation files are searched in.
113 *
114 * @param string $directory directory path
115 *
116 * @return $this
117 */
118 public function removeDirectory(string $directory)
119 {
120 $search = \rtrim(\strtr($directory, '\\', '/'), '/');
121 return $this->setDirectories(\array_filter($this->getDirectories(), function ($item) use($search) {
122 return \rtrim(\strtr($item, '\\', '/'), '/') !== $search;
123 }));
124 }
125 /**
126 * Reset messages of a locale (all locale if no locale passed).
127 * Remove custom messages and reload initial messages from matching
128 * file in Lang directory.
129 *
130 * @param string|null $locale
131 *
132 * @return bool
133 */
134 public function resetMessages($locale = null)
135 {
136 if ($locale === null) {
137 $this->messages = [];
138 return \true;
139 }
140 $this->assertValidLocale($locale);
141 foreach ($this->getDirectories() as $directory) {
142 $data = @(include \sprintf('%s/%s.php', \rtrim($directory, '\\/'), $locale));
143 if ($data !== \false) {
144 $this->messages[$locale] = $data;
145 $this->addResource('array', $this->messages[$locale], $locale);
146 return \true;
147 }
148 }
149 return \false;
150 }
151 /**
152 * Returns the list of files matching a given locale prefix (or all if empty).
153 *
154 * @param string $prefix prefix required to filter result
155 *
156 * @return array
157 */
158 public function getLocalesFiles($prefix = '')
159 {
160 $files = [];
161 foreach ($this->getDirectories() as $directory) {
162 $directory = \rtrim($directory, '\\/');
163 foreach (\glob("{$directory}/{$prefix}*.php") as $file) {
164 $files[] = $file;
165 }
166 }
167 return \array_unique($files);
168 }
169 /**
170 * Returns the list of internally available locales and already loaded custom locales.
171 * (It will ignore custom translator dynamic loading.)
172 *
173 * @param string $prefix prefix required to filter result
174 *
175 * @return array
176 */
177 public function getAvailableLocales($prefix = '')
178 {
179 $locales = [];
180 foreach ($this->getLocalesFiles($prefix) as $file) {
181 $locales[] = \substr($file, \strrpos($file, '/') + 1, -4);
182 }
183 return \array_unique(\array_merge($locales, \array_keys($this->messages)));
184 }
185 protected function translate(?string $id, array $parameters = [], ?string $domain = null, ?string $locale = null) : string
186 {
187 if ($domain === null) {
188 $domain = 'messages';
189 }
190 $catalogue = $this->getCatalogue($locale);
191 $format = $this instanceof TranslatorStrongTypeInterface ? $this->getFromCatalogue($catalogue, (string) $id, $domain) : $this->getCatalogue($locale)->get((string) $id, $domain);
192 // @codeCoverageIgnore
193 if ($format instanceof Closure) {
194 // @codeCoverageIgnoreStart
195 try {
196 $count = (new ReflectionFunction($format))->getNumberOfRequiredParameters();
197 } catch (ReflectionException $exception) {
198 $count = 0;
199 }
200 // @codeCoverageIgnoreEnd
201 return $format(...\array_values($parameters), ...\array_fill(0, \max(0, $count - \count($parameters)), null));
202 }
203 return parent::trans($id, $parameters, $domain, $locale);
204 }
205 /**
206 * Init messages language from matching file in Lang directory.
207 *
208 * @param string $locale
209 *
210 * @return bool
211 */
212 protected function loadMessagesFromFile($locale)
213 {
214 return isset($this->messages[$locale]) || $this->resetMessages($locale);
215 }
216 /**
217 * Set messages of a locale and take file first if present.
218 *
219 * @param string $locale
220 * @param array $messages
221 *
222 * @return $this
223 */
224 public function setMessages($locale, $messages)
225 {
226 $this->loadMessagesFromFile($locale);
227 $this->addResource('array', $messages, $locale);
228 $this->messages[$locale] = \array_merge($this->messages[$locale] ?? [], $messages);
229 return $this;
230 }
231 /**
232 * Set messages of the current locale and take file first if present.
233 *
234 * @param array $messages
235 *
236 * @return $this
237 */
238 public function setTranslations($messages)
239 {
240 return $this->setMessages($this->getLocale(), $messages);
241 }
242 /**
243 * Get messages of a locale, if none given, return all the
244 * languages.
245 *
246 * @param string|null $locale
247 *
248 * @return array
249 */
250 public function getMessages($locale = null)
251 {
252 return $locale === null ? $this->messages : $this->messages[$locale];
253 }
254 /**
255 * Set the current translator locale and indicate if the source locale file exists
256 *
257 * @param string $locale locale ex. en
258 *
259 * @return bool
260 */
261 public function setLocale($locale)
262 {
263 $locale = \preg_replace_callback('/[-_]([a-z]{2,}|\\d{2,})/', function ($matches) {
264 // _2-letters or YUE is a region, _3+-letters is a variant
265 $upper = \strtoupper($matches[1]);
266 if ($upper === 'YUE' || $upper === 'ISO' || \strlen($upper) < 3) {
267 return "_{$upper}";
268 }
269 return '_' . \ucfirst($matches[1]);
270 }, \strtolower($locale));
271 $previousLocale = $this->getLocale();
272 if ($previousLocale === $locale && isset($this->messages[$locale])) {
273 return \true;
274 }
275 unset(static::$singletons[$previousLocale]);
276 if ($locale === 'auto') {
277 $completeLocale = \setlocale(\LC_TIME, '0');
278 $locale = \preg_replace('/^([^_.-]+).*$/', '$1', $completeLocale);
279 $locales = $this->getAvailableLocales($locale);
280 $completeLocaleChunks = \preg_split('/[_.-]+/', $completeLocale);
281 $getScore = function ($language) use($completeLocaleChunks) {
282 return self::compareChunkLists($completeLocaleChunks, \preg_split('/[_.-]+/', $language));
283 };
284 \usort($locales, function ($first, $second) use($getScore) {
285 return $getScore($second) <=> $getScore($first);
286 });
287 $locale = $locales[0];
288 }
289 if (isset($this->aliases[$locale])) {
290 $locale = $this->aliases[$locale];
291 }
292 // If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback
293 if (\str_contains($locale, '_') && $this->loadMessagesFromFile($macroLocale = \preg_replace('/^([^_]+).*$/', '$1', $locale))) {
294 parent::setLocale($macroLocale);
295 }
296 if (!$this->loadMessagesFromFile($locale) && !$this->initializing) {
297 return \false;
298 }
299 parent::setLocale($locale);
300 return \true;
301 }
302 /**
303 * Show locale on var_dump().
304 *
305 * @return array
306 */
307 public function __debugInfo()
308 {
309 return ['locale' => $this->getLocale()];
310 }
311 private static function compareChunkLists($referenceChunks, $chunks)
312 {
313 $score = 0;
314 foreach ($referenceChunks as $index => $chunk) {
315 if (!isset($chunks[$index])) {
316 $score++;
317 continue;
318 }
319 if (\strtolower($chunks[$index]) === \strtolower($chunk)) {
320 $score += 10;
321 }
322 }
323 return $score;
324 }
325 }
326