Subversion-Projekte lars-tiefland.laravel_shop

Revision

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