123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- <?php
-
- namespace Illuminate\Translation;
-
- use Countable;
- use Illuminate\Support\Arr;
- use Illuminate\Support\Str;
- use Illuminate\Support\Collection;
- use Illuminate\Support\Traits\Macroable;
- use Illuminate\Contracts\Translation\Loader;
- use Illuminate\Support\NamespacedItemResolver;
- use Illuminate\Contracts\Translation\Translator as TranslatorContract;
-
- class Translator extends NamespacedItemResolver implements TranslatorContract
- {
- use Macroable;
-
- /**
- * The loader implementation.
- *
- * @var \Illuminate\Contracts\Translation\Loader
- */
- protected $loader;
-
- /**
- * The default locale being used by the translator.
- *
- * @var string
- */
- protected $locale;
-
- /**
- * The fallback locale used by the translator.
- *
- * @var string
- */
- protected $fallback;
-
- /**
- * The array of loaded translation groups.
- *
- * @var array
- */
- protected $loaded = [];
-
- /**
- * The message selector.
- *
- * @var \Illuminate\Translation\MessageSelector
- */
- protected $selector;
-
- /**
- * Create a new translator instance.
- *
- * @param \Illuminate\Contracts\Translation\Loader $loader
- * @param string $locale
- * @return void
- */
- public function __construct(Loader $loader, $locale)
- {
- $this->loader = $loader;
- $this->locale = $locale;
- }
-
- /**
- * Determine if a translation exists for a given locale.
- *
- * @param string $key
- * @param string|null $locale
- * @return bool
- */
- public function hasForLocale($key, $locale = null)
- {
- return $this->has($key, $locale, false);
- }
-
- /**
- * Determine if a translation exists.
- *
- * @param string $key
- * @param string|null $locale
- * @param bool $fallback
- * @return bool
- */
- public function has($key, $locale = null, $fallback = true)
- {
- return $this->get($key, [], $locale, $fallback) !== $key;
- }
-
- /**
- * Get the translation for a given key.
- *
- * @param string $key
- * @param array $replace
- * @param string $locale
- * @return string|array|null
- */
- public function trans($key, array $replace = [], $locale = null)
- {
- return $this->get($key, $replace, $locale);
- }
-
- /**
- * Get the translation for the given key.
- *
- * @param string $key
- * @param array $replace
- * @param string|null $locale
- * @param bool $fallback
- * @return string|array|null
- */
- public function get($key, array $replace = [], $locale = null, $fallback = true)
- {
- list($namespace, $group, $item) = $this->parseKey($key);
-
- // Here we will get the locale that should be used for the language line. If one
- // was not passed, we will use the default locales which was given to us when
- // the translator was instantiated. Then, we can load the lines and return.
- $locales = $fallback ? $this->localeArray($locale)
- : [$locale ?: $this->locale];
-
- foreach ($locales as $locale) {
- if (! is_null($line = $this->getLine(
- $namespace, $group, $locale, $item, $replace
- ))) {
- break;
- }
- }
-
- // If the line doesn't exist, we will return back the key which was requested as
- // that will be quick to spot in the UI if language keys are wrong or missing
- // from the application's language files. Otherwise we can return the line.
- if (isset($line)) {
- return $line;
- }
-
- return $key;
- }
-
- /**
- * Get the translation for a given key from the JSON translation files.
- *
- * @param string $key
- * @param array $replace
- * @param string $locale
- * @return string|array|null
- */
- public function getFromJson($key, array $replace = [], $locale = null)
- {
- $locale = $locale ?: $this->locale;
-
- // For JSON translations, there is only one file per locale, so we will simply load
- // that file and then we will be ready to check the array for the key. These are
- // only one level deep so we do not need to do any fancy searching through it.
- $this->load('*', '*', $locale);
-
- $line = $this->loaded['*']['*'][$locale][$key] ?? null;
-
- // If we can't find a translation for the JSON key, we will attempt to translate it
- // using the typical translation file. This way developers can always just use a
- // helper such as __ instead of having to pick between trans or __ with views.
- if (! isset($line)) {
- $fallback = $this->get($key, $replace, $locale);
-
- if ($fallback !== $key) {
- return $fallback;
- }
- }
-
- return $this->makeReplacements($line ?: $key, $replace);
- }
-
- /**
- * Get a translation according to an integer value.
- *
- * @param string $key
- * @param int|array|\Countable $number
- * @param array $replace
- * @param string $locale
- * @return string
- */
- public function transChoice($key, $number, array $replace = [], $locale = null)
- {
- return $this->choice($key, $number, $replace, $locale);
- }
-
- /**
- * Get a translation according to an integer value.
- *
- * @param string $key
- * @param int|array|\Countable $number
- * @param array $replace
- * @param string $locale
- * @return string
- */
- public function choice($key, $number, array $replace = [], $locale = null)
- {
- $line = $this->get(
- $key, $replace, $locale = $this->localeForChoice($locale)
- );
-
- // If the given "number" is actually an array or countable we will simply count the
- // number of elements in an instance. This allows developers to pass an array of
- // items without having to count it on their end first which gives bad syntax.
- if (is_array($number) || $number instanceof Countable) {
- $number = count($number);
- }
-
- $replace['count'] = $number;
-
- return $this->makeReplacements(
- $this->getSelector()->choose($line, $number, $locale), $replace
- );
- }
-
- /**
- * Get the proper locale for a choice operation.
- *
- * @param string|null $locale
- * @return string
- */
- protected function localeForChoice($locale)
- {
- return $locale ?: $this->locale ?: $this->fallback;
- }
-
- /**
- * Retrieve a language line out the loaded array.
- *
- * @param string $namespace
- * @param string $group
- * @param string $locale
- * @param string $item
- * @param array $replace
- * @return string|array|null
- */
- protected function getLine($namespace, $group, $locale, $item, array $replace)
- {
- $this->load($namespace, $group, $locale);
-
- $line = Arr::get($this->loaded[$namespace][$group][$locale], $item);
-
- if (is_string($line)) {
- return $this->makeReplacements($line, $replace);
- } elseif (is_array($line) && count($line) > 0) {
- return $line;
- }
- }
-
- /**
- * Make the place-holder replacements on a line.
- *
- * @param string $line
- * @param array $replace
- * @return string
- */
- protected function makeReplacements($line, array $replace)
- {
- if (empty($replace)) {
- return $line;
- }
-
- $replace = $this->sortReplacements($replace);
-
- foreach ($replace as $key => $value) {
- $line = str_replace(
- [':'.$key, ':'.Str::upper($key), ':'.Str::ucfirst($key)],
- [$value, Str::upper($value), Str::ucfirst($value)],
- $line
- );
- }
-
- return $line;
- }
-
- /**
- * Sort the replacements array.
- *
- * @param array $replace
- * @return array
- */
- protected function sortReplacements(array $replace)
- {
- return (new Collection($replace))->sortBy(function ($value, $key) {
- return mb_strlen($key) * -1;
- })->all();
- }
-
- /**
- * Add translation lines to the given locale.
- *
- * @param array $lines
- * @param string $locale
- * @param string $namespace
- * @return void
- */
- public function addLines(array $lines, $locale, $namespace = '*')
- {
- foreach ($lines as $key => $value) {
- list($group, $item) = explode('.', $key, 2);
-
- Arr::set($this->loaded, "$namespace.$group.$locale.$item", $value);
- }
- }
-
- /**
- * Load the specified language group.
- *
- * @param string $namespace
- * @param string $group
- * @param string $locale
- * @return void
- */
- public function load($namespace, $group, $locale)
- {
- if ($this->isLoaded($namespace, $group, $locale)) {
- return;
- }
-
- // The loader is responsible for returning the array of language lines for the
- // given namespace, group, and locale. We'll set the lines in this array of
- // lines that have already been loaded so that we can easily access them.
- $lines = $this->loader->load($locale, $group, $namespace);
-
- $this->loaded[$namespace][$group][$locale] = $lines;
- }
-
- /**
- * Determine if the given group has been loaded.
- *
- * @param string $namespace
- * @param string $group
- * @param string $locale
- * @return bool
- */
- protected function isLoaded($namespace, $group, $locale)
- {
- return isset($this->loaded[$namespace][$group][$locale]);
- }
-
- /**
- * Add a new namespace to the loader.
- *
- * @param string $namespace
- * @param string $hint
- * @return void
- */
- public function addNamespace($namespace, $hint)
- {
- $this->loader->addNamespace($namespace, $hint);
- }
-
- /**
- * Add a new JSON path to the loader.
- *
- * @param string $path
- * @return void
- */
- public function addJsonPath($path)
- {
- $this->loader->addJsonPath($path);
- }
-
- /**
- * Parse a key into namespace, group, and item.
- *
- * @param string $key
- * @return array
- */
- public function parseKey($key)
- {
- $segments = parent::parseKey($key);
-
- if (is_null($segments[0])) {
- $segments[0] = '*';
- }
-
- return $segments;
- }
-
- /**
- * Get the array of locales to be checked.
- *
- * @param string|null $locale
- * @return array
- */
- protected function localeArray($locale)
- {
- return array_filter([$locale ?: $this->locale, $this->fallback]);
- }
-
- /**
- * Get the message selector instance.
- *
- * @return \Illuminate\Translation\MessageSelector
- */
- public function getSelector()
- {
- if (! isset($this->selector)) {
- $this->selector = new MessageSelector;
- }
-
- return $this->selector;
- }
-
- /**
- * Set the message selector instance.
- *
- * @param \Illuminate\Translation\MessageSelector $selector
- * @return void
- */
- public function setSelector(MessageSelector $selector)
- {
- $this->selector = $selector;
- }
-
- /**
- * Get the language line loader implementation.
- *
- * @return \Illuminate\Contracts\Translation\Loader
- */
- public function getLoader()
- {
- return $this->loader;
- }
-
- /**
- * Get the default locale being used.
- *
- * @return string
- */
- public function locale()
- {
- return $this->getLocale();
- }
-
- /**
- * Get the default locale being used.
- *
- * @return string
- */
- public function getLocale()
- {
- return $this->locale;
- }
-
- /**
- * Set the default locale.
- *
- * @param string $locale
- * @return void
- */
- public function setLocale($locale)
- {
- $this->locale = $locale;
- }
-
- /**
- * Get the fallback locale being used.
- *
- * @return string
- */
- public function getFallback()
- {
- return $this->fallback;
- }
-
- /**
- * Set the fallback locale being used.
- *
- * @param string $fallback
- * @return void
- */
- public function setFallback($fallback)
- {
- $this->fallback = $fallback;
- }
-
- /**
- * Set the loaded translation groups.
- *
- * @param array $loaded
- * @return void
- */
- public function setLoaded(array $loaded)
- {
- $this->loaded = $loaded;
- }
- }
|