Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 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\Contracts\Translation;
13
 
14
use Symfony\Component\Translation\Exception\InvalidArgumentException;
15
 
16
/**
17
 * A trait to help implement TranslatorInterface and LocaleAwareInterface.
18
 *
19
 * @author Fabien Potencier <fabien@symfony.com>
20
 */
21
trait TranslatorTrait
22
{
23
    private ?string $locale = null;
24
 
25
    public function setLocale(string $locale)
26
    {
27
        $this->locale = $locale;
28
    }
29
 
30
    public function getLocale(): string
31
    {
32
        return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
33
    }
34
 
35
    public function trans(?string $id, array $parameters = [], string $domain = null, string $locale = null): string
36
    {
37
        if (null === $id || '' === $id) {
38
            return '';
39
        }
40
 
41
        if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) {
42
            return strtr($id, $parameters);
43
        }
44
 
45
        $number = (float) $parameters['%count%'];
46
        $locale = $locale ?: $this->getLocale();
47
 
48
        $parts = [];
49
        if (preg_match('/^\|++$/', $id)) {
50
            $parts = explode('|', $id);
51
        } elseif (preg_match_all('/(?:\|\||[^\|])++/', $id, $matches)) {
52
            $parts = $matches[0];
53
        }
54
 
55
        $intervalRegexp = <<<'EOF'
56
/^(?P<interval>
57
    ({\s*
58
        (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
59
    \s*})
60
 
61
        |
62
 
63
    (?P<left_delimiter>[\[\]])
64
        \s*
65
        (?P<left>-Inf|\-?\d+(\.\d+)?)
66
        \s*,\s*
67
        (?P<right>\+?Inf|\-?\d+(\.\d+)?)
68
        \s*
69
    (?P<right_delimiter>[\[\]])
70
)\s*(?P<message>.*?)$/xs
71
EOF;
72
 
73
        $standardRules = [];
74
        foreach ($parts as $part) {
75
            $part = trim(str_replace('||', '|', $part));
76
 
77
            // try to match an explicit rule, then fallback to the standard ones
78
            if (preg_match($intervalRegexp, $part, $matches)) {
79
                if ($matches[2]) {
80
                    foreach (explode(',', $matches[3]) as $n) {
81
                        if ($number == $n) {
82
                            return strtr($matches['message'], $parameters);
83
                        }
84
                    }
85
                } else {
86
                    $leftNumber = '-Inf' === $matches['left'] ? -\INF : (float) $matches['left'];
87
                    $rightNumber = is_numeric($matches['right']) ? (float) $matches['right'] : \INF;
88
 
89
                    if (('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
90
                        && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
91
                    ) {
92
                        return strtr($matches['message'], $parameters);
93
                    }
94
                }
95
            } elseif (preg_match('/^\w+\:\s*(.*?)$/', $part, $matches)) {
96
                $standardRules[] = $matches[1];
97
            } else {
98
                $standardRules[] = $part;
99
            }
100
        }
101
 
102
        $position = $this->getPluralizationRule($number, $locale);
103
 
104
        if (!isset($standardRules[$position])) {
105
            // when there's exactly one rule given, and that rule is a standard
106
            // rule, use this rule
107
            if (1 === \count($parts) && isset($standardRules[0])) {
108
                return strtr($standardRules[0], $parameters);
109
            }
110
 
111
            $message = sprintf('Unable to choose a translation for "%s" with locale "%s" for value "%d". Double check that this translation has the correct plural options (e.g. "There is one apple|There are %%count%% apples").', $id, $locale, $number);
112
 
113
            if (class_exists(InvalidArgumentException::class)) {
114
                throw new InvalidArgumentException($message);
115
            }
116
 
117
            throw new \InvalidArgumentException($message);
118
        }
119
 
120
        return strtr($standardRules[$position], $parameters);
121
    }
122
 
123
    /**
124
     * Returns the plural position to use for the given locale and number.
125
     *
126
     * The plural rules are derived from code of the Zend Framework (2010-09-25),
127
     * which is subject to the new BSD license (http://framework.zend.com/license/new-bsd).
128
     * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
129
     */
130
    private function getPluralizationRule(float $number, string $locale): int
131
    {
132
        $number = abs($number);
133
 
134
        return match ('pt_BR' !== $locale && 'en_US_POSIX' !== $locale && \strlen($locale) > 3 ? substr($locale, 0, strrpos($locale, '_')) : $locale) {
135
            'af',
136
            'bn',
137
            'bg',
138
            'ca',
139
            'da',
140
            'de',
141
            'el',
142
            'en',
143
            'en_US_POSIX',
144
            'eo',
145
            'es',
146
            'et',
147
            'eu',
148
            'fa',
149
            'fi',
150
            'fo',
151
            'fur',
152
            'fy',
153
            'gl',
154
            'gu',
155
            'ha',
156
            'he',
157
            'hu',
158
            'is',
159
            'it',
160
            'ku',
161
            'lb',
162
            'ml',
163
            'mn',
164
            'mr',
165
            'nah',
166
            'nb',
167
            'ne',
168
            'nl',
169
            'nn',
170
            'no',
171
            'oc',
172
            'om',
173
            'or',
174
            'pa',
175
            'pap',
176
            'ps',
177
            'pt',
178
            'so',
179
            'sq',
180
            'sv',
181
            'sw',
182
            'ta',
183
            'te',
184
            'tk',
185
            'ur',
186
            'zu' => (1 == $number) ? 0 : 1,
187
            'am',
188
            'bh',
189
            'fil',
190
            'fr',
191
            'gun',
192
            'hi',
193
            'hy',
194
            'ln',
195
            'mg',
196
            'nso',
197
            'pt_BR',
198
            'ti',
199
            'wa' => ($number < 2) ? 0 : 1,
200
            'be',
201
            'bs',
202
            'hr',
203
            'ru',
204
            'sh',
205
            'sr',
206
            'uk' => ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2),
207
            'cs',
208
            'sk' => (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2),
209
            'ga' => (1 == $number) ? 0 : ((2 == $number) ? 1 : 2),
210
            'lt' => ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2),
211
            'sl' => (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)),
212
            'mk' => (1 == $number % 10) ? 0 : 1,
213
            'mt' => (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)),
214
            'lv' => (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2),
215
            'pl' => (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2),
216
            'cy' => (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)),
217
            'ro' => (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2),
218
            'ar' => (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))),
219
            default => 0,
220
        };
221
    }
222
}