-
Notifications
You must be signed in to change notification settings - Fork 0
/
LocalesManager.php
273 lines (239 loc) · 6.77 KB
/
LocalesManager.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
<?php
namespace Charcoal\Translator;
use InvalidArgumentException;
/**
* Locales Manager
*
* The manager handles the collection of available languages, their definitions,
* the default language, and tracks the current language.
*/
class LocalesManager
{
/**
* Default sorting priority for locales.
*
* @const integer
*/
public const DEFAULT_SORT_PRIORITY = 10;
/**
* Dictionary of language definitions.
*
* @var array
*/
private $locales;
/**
* List of language codes.
*
* @var string[]
*/
private $languages;
/**
* Language code for the default locale.
*
* @var string
*/
private $defaultLanguage;
/**
* Language code for the current locale.
*
* @var string|null
*/
private $currentLanguage;
/**
* Create the Locales Manager with locales and optional options.
*
* Required parameters:
* - **locales** (`array`)
*
* Optional parameters:
* - **default_language** (`string`)
* - If none is set, the first language (from _locales_) will be used.
* - **current_language** (`string`)
* - If none is set, then the default language will be used.
*
* @param array $data Constructor dependencies.
* @throws InvalidArgumentException If the default language is not a valid language.
*/
public function __construct(array $data)
{
$this->setLocales($data['locales']);
$default = isset($data['default_language']) ? $data['default_language'] : null;
$this->setDefaultLocale($default);
$current = isset($data['current_language']) ? $data['current_language'] : null;
$this->setCurrentLocale($current);
}
/**
* Retrieve the available locales information.
*
* @return array
*/
public function locales()
{
return $this->locales;
}
/**
* Retrieve the available locales (language codes).
*
* @return string[]
*/
public function availableLocales()
{
return $this->languages;
}
/**
* Set the default language.
*
* @param string|null $lang The default language code.
* If NULL, the first language is assigned.
* @throws InvalidArgumentException If the language is invalid.
* @return void
*/
private function setDefaultLocale($lang)
{
if ($lang === null) {
$this->defaultLanguage = $this->languages[0];
return;
}
if (!$this->hasLocale($lang)) {
if (!is_string($lang)) {
$lang = is_object($lang) ? get_class($lang) : gettype($lang);
}
throw new InvalidArgumentException(sprintf(
'Unsupported default language; must be one of "%s", received "%s"',
implode(', ', $this->availableLocales()),
$lang
));
}
$this->defaultLanguage = $lang;
}
/**
* Retrieve the default language.
*
* @return string
*/
public function defaultLocale()
{
return $this->defaultLanguage;
}
/**
* Set the current language.
*
* @param string|null $lang The current language code.
* If NULL, the current language is unset.
* @throws InvalidArgumentException If the language is invalid.
* @return void
*/
public function setCurrentLocale($lang)
{
if ($lang === null) {
$this->currentLanguage = null;
return;
}
if (!$this->hasLocale($lang)) {
if (!is_string($lang)) {
$lang = is_object($lang) ? get_class($lang) : gettype($lang);
}
throw new InvalidArgumentException(sprintf(
'Unsupported language; must be one of "%s", received "%s"',
implode(', ', $this->availableLocales()),
$lang
));
}
$this->currentLanguage = $lang;
}
/**
* Retrieve the current language.
*
* @return string
*/
public function currentLocale()
{
if ($this->currentLanguage === null) {
return $this->defaultLanguage;
}
return $this->currentLanguage;
}
/**
* Determine if a locale is available.
*
* @param string $lang The language code to check.
* @return boolean
*/
public function hasLocale($lang)
{
return isset($this->locales[$lang]);
}
/**
* Set the available languages.
*
* Ensure that explicitely inactive locales are excluded and that the required
* values are set on the locales configuration structure.
*
* This method is only called from the constructor.
*
* @param array $locales The locales configuration structure.
* @throws InvalidArgumentException If there are no active locales.
* @return void
*/
private function setLocales(array $locales)
{
$locales = $this->filterLocales($locales);
uasort($locales, [ $this, 'sortLocalesByPriority' ]);
$this->locales = [];
$this->languages = [];
foreach ($locales as $langCode => $locale) {
$this->locales[$langCode] = $locale;
$this->languages[] = $langCode;
}
if (empty($this->locales)) {
throw new InvalidArgumentException(
'Locales can not be empty.'
);
}
}
/**
* Filter the available languages.
*
* Routine:
* 1. Removes disabled languages
* 2. Assigns a priority, if absent
* 3. Assigns a locale, if absent
*
* @param array $locales The locales configuration structure.
* @return array The parsed language structures.
*/
private function filterLocales(array $locales)
{
$z = self::DEFAULT_SORT_PRIORITY;
$filteredLocales = [];
foreach ($locales as $langCode => $locale) {
if (isset($locale['active']) && !$locale['active']) {
continue;
}
if (!isset($locale['priority'])) {
$locale['priority'] = $z++;
}
if (!isset($locale['locale'])) {
$locale['locale'] = $langCode;
}
$filteredLocales[$langCode] = $locale;
}
return $filteredLocales;
}
/**
* To be called with {@see uasort()}.
*
* @param array $a Sortable action A.
* @param array $b Sortable action B.
* @return integer
*/
private function sortLocalesByPriority(array $a, array $b)
{
$a = isset($a['priority']) ? $a['priority'] : 0;
$b = isset($b['priority']) ? $b['priority'] : 0;
if ($a === $b) {
return 0;
}
return ($a < $b) ? (-1) : 1;
}
}