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
namespace Illuminate\Translation;
4
 
5
use Illuminate\Contracts\Translation\Loader;
6
use Illuminate\Contracts\Translation\Translator as TranslatorContract;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\NamespacedItemResolver;
9
use Illuminate\Support\Str;
10
use Illuminate\Support\Traits\Macroable;
11
use InvalidArgumentException;
12
 
13
class Translator extends NamespacedItemResolver implements TranslatorContract
14
{
15
    use Macroable;
16
 
17
    /**
18
     * The loader implementation.
19
     *
20
     * @var \Illuminate\Contracts\Translation\Loader
21
     */
22
    protected $loader;
23
 
24
    /**
25
     * The default locale being used by the translator.
26
     *
27
     * @var string
28
     */
29
    protected $locale;
30
 
31
    /**
32
     * The fallback locale used by the translator.
33
     *
34
     * @var string
35
     */
36
    protected $fallback;
37
 
38
    /**
39
     * The array of loaded translation groups.
40
     *
41
     * @var array
42
     */
43
    protected $loaded = [];
44
 
45
    /**
46
     * The message selector.
47
     *
48
     * @var \Illuminate\Translation\MessageSelector
49
     */
50
    protected $selector;
51
 
52
    /**
53
     * The callable that should be invoked to determine applicable locales.
54
     *
55
     * @var callable
56
     */
57
    protected $determineLocalesUsing;
58
 
59
    /**
60
     * Create a new translator instance.
61
     *
62
     * @param  \Illuminate\Contracts\Translation\Loader  $loader
63
     * @param  string  $locale
64
     * @return void
65
     */
66
    public function __construct(Loader $loader, $locale)
67
    {
68
        $this->loader = $loader;
69
 
70
        $this->setLocale($locale);
71
    }
72
 
73
    /**
74
     * Determine if a translation exists for a given locale.
75
     *
76
     * @param  string  $key
77
     * @param  string|null  $locale
78
     * @return bool
79
     */
80
    public function hasForLocale($key, $locale = null)
81
    {
82
        return $this->has($key, $locale, false);
83
    }
84
 
85
    /**
86
     * Determine if a translation exists.
87
     *
88
     * @param  string  $key
89
     * @param  string|null  $locale
90
     * @param  bool  $fallback
91
     * @return bool
92
     */
93
    public function has($key, $locale = null, $fallback = true)
94
    {
95
        return $this->get($key, [], $locale, $fallback) !== $key;
96
    }
97
 
98
    /**
99
     * Get the translation for the given key.
100
     *
101
     * @param  string  $key
102
     * @param  array  $replace
103
     * @param  string|null  $locale
104
     * @param  bool  $fallback
105
     * @return string|array
106
     */
107
    public function get($key, array $replace = [], $locale = null, $fallback = true)
108
    {
109
        $locale = $locale ?: $this->locale;
110
 
111
        // For JSON translations, there is only one file per locale, so we will simply load
112
        // that file and then we will be ready to check the array for the key. These are
113
        // only one level deep so we do not need to do any fancy searching through it.
114
        $this->load('*', '*', $locale);
115
 
116
        $line = $this->loaded['*']['*'][$locale][$key] ?? null;
117
 
118
        // If we can't find a translation for the JSON key, we will attempt to translate it
119
        // using the typical translation file. This way developers can always just use a
120
        // helper such as __ instead of having to pick between trans or __ with views.
121
        if (! isset($line)) {
122
            [$namespace, $group, $item] = $this->parseKey($key);
123
 
124
            // Here we will get the locale that should be used for the language line. If one
125
            // was not passed, we will use the default locales which was given to us when
126
            // the translator was instantiated. Then, we can load the lines and return.
127
            $locales = $fallback ? $this->localeArray($locale) : [$locale];
128
 
129
            foreach ($locales as $locale) {
130
                if (! is_null($line = $this->getLine(
131
                    $namespace, $group, $locale, $item, $replace
132
                ))) {
133
                    return $line;
134
                }
135
            }
136
        }
137
 
138
        // If the line doesn't exist, we will return back the key which was requested as
139
        // that will be quick to spot in the UI if language keys are wrong or missing
140
        // from the application's language files. Otherwise we can return the line.
141
        return $this->makeReplacements($line ?: $key, $replace);
142
    }
143
 
144
    /**
145
     * Get a translation according to an integer value.
146
     *
147
     * @param  string  $key
148
     * @param  \Countable|int|array  $number
149
     * @param  array  $replace
150
     * @param  string|null  $locale
151
     * @return string
152
     */
153
    public function choice($key, $number, array $replace = [], $locale = null)
154
    {
155
        $line = $this->get(
156
            $key, $replace, $locale = $this->localeForChoice($locale)
157
        );
158
 
159
        // If the given "number" is actually an array or countable we will simply count the
160
        // number of elements in an instance. This allows developers to pass an array of
161
        // items without having to count it on their end first which gives bad syntax.
162
        if (is_countable($number)) {
163
            $number = count($number);
164
        }
165
 
166
        $replace['count'] = $number;
167
 
168
        return $this->makeReplacements(
169
            $this->getSelector()->choose($line, $number, $locale), $replace
170
        );
171
    }
172
 
173
    /**
174
     * Get the proper locale for a choice operation.
175
     *
176
     * @param  string|null  $locale
177
     * @return string
178
     */
179
    protected function localeForChoice($locale)
180
    {
181
        return $locale ?: $this->locale ?: $this->fallback;
182
    }
183
 
184
    /**
185
     * Retrieve a language line out the loaded array.
186
     *
187
     * @param  string  $namespace
188
     * @param  string  $group
189
     * @param  string  $locale
190
     * @param  string  $item
191
     * @param  array  $replace
192
     * @return string|array|null
193
     */
194
    protected function getLine($namespace, $group, $locale, $item, array $replace)
195
    {
196
        $this->load($namespace, $group, $locale);
197
 
198
        $line = Arr::get($this->loaded[$namespace][$group][$locale], $item);
199
 
200
        if (is_string($line)) {
201
            return $this->makeReplacements($line, $replace);
202
        } elseif (is_array($line) && count($line) > 0) {
203
            array_walk_recursive($line, function (&$value, $key) use ($replace) {
204
                $value = $this->makeReplacements($value, $replace);
205
            });
206
 
207
            return $line;
208
        }
209
    }
210
 
211
    /**
212
     * Make the place-holder replacements on a line.
213
     *
214
     * @param  string  $line
215
     * @param  array  $replace
216
     * @return string
217
     */
218
    protected function makeReplacements($line, array $replace)
219
    {
220
        if (empty($replace)) {
221
            return $line;
222
        }
223
 
224
        $shouldReplace = [];
225
 
226
        foreach ($replace as $key => $value) {
227
            $shouldReplace[':'.Str::ucfirst($key ?? '')] = Str::ucfirst($value ?? '');
228
            $shouldReplace[':'.Str::upper($key ?? '')] = Str::upper($value ?? '');
229
            $shouldReplace[':'.$key] = $value;
230
        }
231
 
232
        return strtr($line, $shouldReplace);
233
    }
234
 
235
    /**
236
     * Add translation lines to the given locale.
237
     *
238
     * @param  array  $lines
239
     * @param  string  $locale
240
     * @param  string  $namespace
241
     * @return void
242
     */
243
    public function addLines(array $lines, $locale, $namespace = '*')
244
    {
245
        foreach ($lines as $key => $value) {
246
            [$group, $item] = explode('.', $key, 2);
247
 
248
            Arr::set($this->loaded, "$namespace.$group.$locale.$item", $value);
249
        }
250
    }
251
 
252
    /**
253
     * Load the specified language group.
254
     *
255
     * @param  string  $namespace
256
     * @param  string  $group
257
     * @param  string  $locale
258
     * @return void
259
     */
260
    public function load($namespace, $group, $locale)
261
    {
262
        if ($this->isLoaded($namespace, $group, $locale)) {
263
            return;
264
        }
265
 
266
        // The loader is responsible for returning the array of language lines for the
267
        // given namespace, group, and locale. We'll set the lines in this array of
268
        // lines that have already been loaded so that we can easily access them.
269
        $lines = $this->loader->load($locale, $group, $namespace);
270
 
271
        $this->loaded[$namespace][$group][$locale] = $lines;
272
    }
273
 
274
    /**
275
     * Determine if the given group has been loaded.
276
     *
277
     * @param  string  $namespace
278
     * @param  string  $group
279
     * @param  string  $locale
280
     * @return bool
281
     */
282
    protected function isLoaded($namespace, $group, $locale)
283
    {
284
        return isset($this->loaded[$namespace][$group][$locale]);
285
    }
286
 
287
    /**
288
     * Add a new namespace to the loader.
289
     *
290
     * @param  string  $namespace
291
     * @param  string  $hint
292
     * @return void
293
     */
294
    public function addNamespace($namespace, $hint)
295
    {
296
        $this->loader->addNamespace($namespace, $hint);
297
    }
298
 
299
    /**
300
     * Add a new JSON path to the loader.
301
     *
302
     * @param  string  $path
303
     * @return void
304
     */
305
    public function addJsonPath($path)
306
    {
307
        $this->loader->addJsonPath($path);
308
    }
309
 
310
    /**
311
     * Parse a key into namespace, group, and item.
312
     *
313
     * @param  string  $key
314
     * @return array
315
     */
316
    public function parseKey($key)
317
    {
318
        $segments = parent::parseKey($key);
319
 
320
        if (is_null($segments[0])) {
321
            $segments[0] = '*';
322
        }
323
 
324
        return $segments;
325
    }
326
 
327
    /**
328
     * Get the array of locales to be checked.
329
     *
330
     * @param  string|null  $locale
331
     * @return array
332
     */
333
    protected function localeArray($locale)
334
    {
335
        $locales = array_filter([$locale ?: $this->locale, $this->fallback]);
336
 
337
        return call_user_func($this->determineLocalesUsing ?: fn () => $locales, $locales);
338
    }
339
 
340
    /**
341
     * Specify a callback that should be invoked to determined the applicable locale array.
342
     *
343
     * @param  callable  $callback
344
     * @return void
345
     */
346
    public function determineLocalesUsing($callback)
347
    {
348
        $this->determineLocalesUsing = $callback;
349
    }
350
 
351
    /**
352
     * Get the message selector instance.
353
     *
354
     * @return \Illuminate\Translation\MessageSelector
355
     */
356
    public function getSelector()
357
    {
358
        if (! isset($this->selector)) {
359
            $this->selector = new MessageSelector;
360
        }
361
 
362
        return $this->selector;
363
    }
364
 
365
    /**
366
     * Set the message selector instance.
367
     *
368
     * @param  \Illuminate\Translation\MessageSelector  $selector
369
     * @return void
370
     */
371
    public function setSelector(MessageSelector $selector)
372
    {
373
        $this->selector = $selector;
374
    }
375
 
376
    /**
377
     * Get the language line loader implementation.
378
     *
379
     * @return \Illuminate\Contracts\Translation\Loader
380
     */
381
    public function getLoader()
382
    {
383
        return $this->loader;
384
    }
385
 
386
    /**
387
     * Get the default locale being used.
388
     *
389
     * @return string
390
     */
391
    public function locale()
392
    {
393
        return $this->getLocale();
394
    }
395
 
396
    /**
397
     * Get the default locale being used.
398
     *
399
     * @return string
400
     */
401
    public function getLocale()
402
    {
403
        return $this->locale;
404
    }
405
 
406
    /**
407
     * Set the default locale.
408
     *
409
     * @param  string  $locale
410
     * @return void
411
     *
412
     * @throws \InvalidArgumentException
413
     */
414
    public function setLocale($locale)
415
    {
416
        if (Str::contains($locale, ['/', '\\'])) {
417
            throw new InvalidArgumentException('Invalid characters present in locale.');
418
        }
419
 
420
        $this->locale = $locale;
421
    }
422
 
423
    /**
424
     * Get the fallback locale being used.
425
     *
426
     * @return string
427
     */
428
    public function getFallback()
429
    {
430
        return $this->fallback;
431
    }
432
 
433
    /**
434
     * Set the fallback locale being used.
435
     *
436
     * @param  string  $fallback
437
     * @return void
438
     */
439
    public function setFallback($fallback)
440
    {
441
        $this->fallback = $fallback;
442
    }
443
 
444
    /**
445
     * Set the loaded translation groups.
446
     *
447
     * @param  array  $loaded
448
     * @return void
449
     */
450
    public function setLoaded(array $loaded)
451
    {
452
        $this->loaded = $loaded;
453
    }
454
}