Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Translation/Translator.php
Строк: 580
<?php

namespace IlluminateTranslation;

use 
Closure;
use 
IlluminateContractsTranslationLoader;
use 
IlluminateContractsTranslationTranslator as TranslatorContract;
use 
IlluminateSupportArr;
use 
IlluminateSupportNamespacedItemResolver;
use 
IlluminateSupportStr;
use 
IlluminateSupportTraitsMacroable;
use 
IlluminateSupportTraitsReflectsClosures;
use 
InvalidArgumentException;

class 
Translator extends NamespacedItemResolver implements TranslatorContract
{
    use 
MacroableReflectsClosures;

    
/**
     * The loader implementation.
     *
     * @var IlluminateContractsTranslationLoader
     */
    
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 IlluminateTranslationMessageSelector
     */
    
protected $selector;

    
/**
     * The callable that should be invoked to determine applicable locales.
     *
     * @var callable
     */
    
protected $determineLocalesUsing;

    
/**
     * The custom rendering callbacks for stringable objects.
     *
     * @var array
     */
    
protected $stringableHandlers = [];

    
/**
     * The callback that is responsible for handling missing translation keys.
     *
     * @var callable|null
     */
    
protected $missingTranslationKeyCallback;

    
/**
     * Indicates whether missing translation keys should be handled.
     *
     * @var bool
     */
    
protected $handleMissingTranslationKeys true;

    
/**
     * Create a new translator instance.
     *
     * @param  IlluminateContractsTranslationLoader  $loader
     * @param  string  $locale
     * @return void
     */
    
public function __construct(Loader $loader$locale)
    {
        
$this->loader $loader;

        
$this->setLocale($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$localefalse);
    }

    
/**
     * 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)
    {
        
$locale $locale ?: $this->locale;

        
$line $this->get($key, [], $locale$fallback);

        
// For JSON translations, the loaded files will contain the correct line.
        // Otherwise, we must assume we are handling typical translation file
        // and check if the returned line is not the same as the given key.
        
if (! is_null($this->loaded['*']['*'][$locale][$key] ?? null)) {
            return 
true;
        }

        return 
$line !== $key;
    }

    
/**
     * Get the translation for the given key.
     *
     * @param  string  $key
     * @param  array  $replace
     * @param  string|null  $locale
     * @param  bool  $fallback
     * @return string|array
     */
    
public function get($key, array $replace = [], $locale null$fallback true)
    {
        
$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)) {
            [
$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];

            foreach (
$locales as $languageLineLocale) {
                if (! 
is_null($line $this->getLine(
                    
$namespace$group$languageLineLocale$item$replace
                
))) {
                    return 
$line;
                }
            }

            
$key $this->handleMissingTranslationKey(
                
$key$replace$locale$fallback
            
);
        }

        
// 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.
        
return $this->makeReplacements($line ?: $key$replace);
    }

    
/**
     * Get a translation according to an integer value.
     *
     * @param  string  $key
     * @param  Countable|int|float|array  $number
     * @param  array  $replace
     * @param  string|null  $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_countable($number)) {
            
$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) {
            
array_walk_recursive($line, function (&$value$key) use ($replace) {
                
$value $this->makeReplacements($value$replace);
            });

            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;
        }

        
$shouldReplace = [];

        foreach (
$replace as $key => $value) {
            if (
is_object($value) && isset($this->stringableHandlers[get_class($value)])) {
                
$value call_user_func($this->stringableHandlers[get_class($value)], $value);
            }

            
$shouldReplace[':'.Str::ucfirst($key ?? '')] = Str::ucfirst($value ?? '');
            
$shouldReplace[':'.Str::upper($key ?? '')] = Str::upper($value ?? '');
            
$shouldReplace[':'.$key] = $value;
        }

        return 
strtr($line$shouldReplace);
    }

    
/**
     * 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) {
            [
$group$item] = explode('.'$key2);

            
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]);
    }

    
/**
     * Handle a missing translation key.
     *
     * @param  string  $key
     * @param  array  $replace
     * @param  string|null  $locale
     * @param  bool  $fallback
     * @return string
     */
    
protected function handleMissingTranslationKey($key$replace$locale$fallback)
    {
        if (! 
$this->handleMissingTranslationKeys ||
            ! isset(
$this->missingTranslationKeyCallback)) {
            return 
$key;
        }

        
// Prevent infinite loops...
        
$this->handleMissingTranslationKeys false;

        
$key call_user_func(
            
$this->missingTranslationKeyCallback,
            
$key$replace$locale$fallback
        
) ?? $key;

        
$this->handleMissingTranslationKeys true;

        return 
$key;
    }

    
/**
     * Register a callback that is responsible for handling missing translation keys.
     *
     * @param  callable|null  $callback
     * @return static
     */
    
public function handleMissingKeysUsing(?callable $callback)
    {
        
$this->missingTranslationKeyCallback $callback;

        return 
$this;
    }

    
/**
     * 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)
    {
        
$locales array_filter([$locale ?: $this->locale$this->fallback]);

        return 
call_user_func($this->determineLocalesUsing ?: fn () => $locales$locales);
    }

    
/**
     * Specify a callback that should be invoked to determined the applicable locale array.
     *
     * @param  callable  $callback
     * @return void
     */
    
public function determineLocalesUsing($callback)
    {
        
$this->determineLocalesUsing $callback;
    }

    
/**
     * Get the message selector instance.
     *
     * @return IlluminateTranslationMessageSelector
     */
    
public function getSelector()
    {
        if (! isset(
$this->selector)) {
            
$this->selector = new MessageSelector;
        }

        return 
$this->selector;
    }

    
/**
     * Set the message selector instance.
     *
     * @param  IlluminateTranslationMessageSelector  $selector
     * @return void
     */
    
public function setSelector(MessageSelector $selector)
    {
        
$this->selector $selector;
    }

    
/**
     * Get the language line loader implementation.
     *
     * @return IlluminateContractsTranslationLoader
     */
    
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
     *
     * @throws InvalidArgumentException
     */
    
public function setLocale($locale)
    {
        if (
Str::contains($locale, ['/''\'])) {
            throw new InvalidArgumentException('
Invalid characters present in 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;
    }

    /**
     * Add a handler to be executed in order to format a given class to a string during translation replacements.
     *
     * @param  callable|string  $class
     * @param  callable|null  $handler
     * @return void
     */
    public function stringable($class, $handler = null)
    {
        if ($class instanceof Closure) {
            [$class, $handler] = [
                $this->firstClosureParameterType($class),
                $class,
            ];
        }

        $this->stringableHandlers[$class] = $handler;
    }
}
Онлайн: 0
Реклама