class ConfigurableLanguageManager

Same name in other branches
  1. 8.9.x core/modules/language/src/ConfigurableLanguageManager.php \Drupal\language\ConfigurableLanguageManager
  2. 10 core/modules/language/src/ConfigurableLanguageManager.php \Drupal\language\ConfigurableLanguageManager
  3. 11.x core/modules/language/src/ConfigurableLanguageManager.php \Drupal\language\ConfigurableLanguageManager

Overrides default LanguageManager to provide configured languages.

Hierarchy

Expanded class hierarchy of ConfigurableLanguageManager

3 files declare their use of ConfigurableLanguageManager
ConfigSubscriber.php in core/modules/language/src/EventSubscriber/ConfigSubscriber.php
ConfigurableLanguage.php in core/modules/language/src/Entity/ConfigurableLanguage.php
EntityConfigBase.php in core/modules/migrate/src/Plugin/migrate/destination/EntityConfigBase.php

File

core/modules/language/src/ConfigurableLanguageManager.php, line 20

Namespace

Drupal\language
View source
class ConfigurableLanguageManager extends LanguageManager implements ConfigurableLanguageManagerInterface {
    
    /**
     * The configuration storage service.
     *
     * @var \Drupal\Core\Config\ConfigFactoryInterface
     */
    protected $configFactory;
    
    /**
     * The module handler service.
     *
     * @var \Drupal\Core\Extension\ModuleHandlerInterface
     */
    protected $moduleHandler;
    
    /**
     * The language configuration override service.
     *
     * @var \Drupal\language\Config\LanguageConfigFactoryOverrideInterface
     */
    protected $configFactoryOverride;
    
    /**
     * The request object.
     *
     * @var \Symfony\Component\HttpFoundation\RequestStack
     */
    protected $requestStack;
    
    /**
     * The language negotiator.
     *
     * @var \Drupal\language\LanguageNegotiatorInterface
     */
    protected $negotiator;
    
    /**
     * Local cache for language type configuration data.
     *
     * @var array
     */
    protected $languageTypes;
    
    /**
     * Local cache for language type information.
     *
     * @var array
     */
    protected $languageTypesInfo;
    
    /**
     * An array of language objects keyed by language type.
     *
     * @var \Drupal\Core\Language\LanguageInterface[]
     */
    protected $negotiatedLanguages;
    
    /**
     * An array of language negotiation method IDs keyed by language type.
     *
     * @var array
     */
    protected $negotiatedMethods;
    
    /**
     * Whether or not the language manager has been initialized.
     *
     * @var bool
     */
    protected $initialized = FALSE;
    
    /**
     * Whether language types are in the process of language initialization.
     *
     * @var bool[]
     */
    protected $initializing = [];
    
    /**
     * {@inheritdoc}
     */
    public static function rebuildServices() {
        \Drupal::service('kernel')->invalidateContainer();
    }
    
    /**
     * Constructs a new ConfigurableLanguageManager object.
     *
     * @param \Drupal\Core\Language\LanguageDefault $default_language
     *   The default language service.
     * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
     *   The configuration factory service.
     * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
     *   The module handler service.
     * @param \Drupal\language\Config\LanguageConfigFactoryOverrideInterface $config_override
     *   The language configuration override service.
     * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
     *   The request stack object.
     */
    public function __construct(LanguageDefault $default_language, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, LanguageConfigFactoryOverrideInterface $config_override, RequestStack $request_stack) {
        $this->defaultLanguage = $default_language;
        $this->configFactory = $config_factory;
        $this->moduleHandler = $module_handler;
        $this->configFactoryOverride = $config_override;
        $this->requestStack = $request_stack;
    }
    
    /**
     * {@inheritdoc}
     */
    public function init() {
        if (!$this->initialized) {
            foreach ($this->getDefinedLanguageTypes() as $type) {
                $this->getCurrentLanguage($type);
            }
            $this->initialized = TRUE;
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function isMultilingual() {
        return count($this->getLanguages(LanguageInterface::STATE_CONFIGURABLE)) > 1;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getLanguageTypes() {
        $this->loadLanguageTypesConfiguration();
        return $this->languageTypes['configurable'];
    }
    
    /**
     * {@inheritdoc}
     */
    public function getDefinedLanguageTypes() {
        $this->loadLanguageTypesConfiguration();
        return $this->languageTypes['all'];
    }
    
    /**
     * Retrieves language types from the configuration storage.
     *
     * @return array
     *   An array of language type names.
     */
    protected function loadLanguageTypesConfiguration() {
        if (!$this->languageTypes) {
            $this->languageTypes = $this->configFactory
                ->get('language.types')
                ->get() ?: [
                'configurable' => [],
                'all' => parent::getLanguageTypes(),
            ];
        }
        return $this->languageTypes;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getDefinedLanguageTypesInfo() {
        if (!isset($this->languageTypesInfo)) {
            $defaults = parent::getDefinedLanguageTypesInfo();
            $info = $this->moduleHandler
                ->invokeAll('language_types_info');
            $language_info = $info + $defaults;
            // Let other modules alter the list of language types.
            $this->moduleHandler
                ->alter('language_types_info', $language_info);
            $this->languageTypesInfo = $language_info;
        }
        return $this->languageTypesInfo;
    }
    
    /**
     * {@inheritdoc}
     */
    public function saveLanguageTypesConfiguration(array $values) {
        $config = $this->configFactory
            ->getEditable('language.types');
        if (isset($values['configurable'])) {
            $config->set('configurable', $values['configurable']);
        }
        if (isset($values['all'])) {
            $config->set('all', $values['all']);
        }
        $config->save(TRUE);
    }
    
    /**
     * {@inheritdoc}
     */
    public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
        if (!isset($this->negotiatedLanguages[$type])) {
            // Ensure we have a valid value for this language type.
            $this->negotiatedLanguages[$type] = $this->getDefaultLanguage();
            if ($this->negotiator && $this->isMultilingual()) {
                if (!isset($this->initializing[$type])) {
                    $this->initializing[$type] = TRUE;
                    $negotiation = $this->negotiator
                        ->initializeType($type);
                    $this->negotiatedLanguages[$type] = reset($negotiation);
                    $this->negotiatedMethods[$type] = key($negotiation);
                    unset($this->initializing[$type]);
                }
                elseif ($type == LanguageInterface::TYPE_INTERFACE) {
                    return new Language([
                        'id' => LanguageInterface::LANGCODE_SYSTEM,
                    ]);
                }
            }
        }
        return $this->negotiatedLanguages[$type];
    }
    
    /**
     * {@inheritdoc}
     */
    public function reset($type = NULL) {
        if (!isset($type)) {
            $this->initialized = FALSE;
            $this->negotiatedLanguages = [];
            $this->negotiatedMethods = [];
            $this->languageTypes = NULL;
            $this->languageTypesInfo = NULL;
            $this->languages = [];
            if ($this->negotiator) {
                $this->negotiator
                    ->reset();
            }
        }
        elseif (isset($this->negotiatedLanguages[$type])) {
            unset($this->negotiatedLanguages[$type]);
            unset($this->negotiatedMethods[$type]);
        }
        return $this;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getNegotiator() {
        return $this->negotiator;
    }
    
    /**
     * {@inheritdoc}
     */
    public function setNegotiator(LanguageNegotiatorInterface $negotiator) {
        $this->negotiator = $negotiator;
        $this->initialized = FALSE;
        $this->negotiatedLanguages = [];
    }
    
    /**
     * {@inheritdoc}
     */
    public function getLanguages($flags = LanguageInterface::STATE_CONFIGURABLE) {
        // If a config override is set, cache using that language's ID.
        if ($override_language = $this->getConfigOverrideLanguage()) {
            $static_cache_id = $override_language->getId();
        }
        else {
            $static_cache_id = $this->getCurrentLanguage()
                ->getId();
        }
        if (!isset($this->languages[$static_cache_id][$flags])) {
            // Initialize the language list with the default language and default
            // locked languages. These cannot be removed. This serves as a fallback
            // list if this method is invoked while the language module is installed
            // and the configuration entities for languages are not yet fully
            // imported.
            $default = $this->getDefaultLanguage();
            $languages = [
                $default->getId() => $default,
            ];
            $languages += $this->getDefaultLockedLanguages($default->getWeight());
            // Load configurable languages on top of the defaults. Ideally this could
            // use the entity API to load and instantiate ConfigurableLanguage
            // objects. However the entity API depends on the language system, so that
            // would result in infinite loops. We use the configuration system
            // directly and instantiate runtime Language objects. When language
            // entities are imported those cover the default and locked languages, so
            // site-specific configuration will prevail over the fallback values.
            // Having them in the array already ensures if this is invoked in the
            // middle of importing language configuration entities, the defaults are
            // always present.
            $config_ids = $this->configFactory
                ->listAll('language.entity.');
            foreach ($this->configFactory
                ->loadMultiple($config_ids) as $config) {
                $data = $config->get();
                $data['name'] = $data['label'];
                $languages[$data['id']] = new Language($data);
            }
            Language::sort($languages);
            // Filter the full list of languages based on the value of $flags.
            $this->languages[$static_cache_id][$flags] = $this->filterLanguages($languages, $flags);
        }
        return $this->languages[$static_cache_id][$flags];
    }
    
    /**
     * {@inheritdoc}
     */
    public function getNativeLanguages() {
        $languages = $this->getLanguages(LanguageInterface::STATE_CONFIGURABLE);
        $natives = [];
        $original_language = $this->getConfigOverrideLanguage();
        foreach ($languages as $langcode => $language) {
            $this->setConfigOverrideLanguage($language);
            $natives[$langcode] = ConfigurableLanguage::load($langcode);
        }
        $this->setConfigOverrideLanguage($original_language);
        Language::sort($natives);
        return $natives;
    }
    
    /**
     * {@inheritdoc}
     */
    public function updateLockedLanguageWeights() {
        // Get the weight of the last configurable language.
        $configurable_languages = $this->getLanguages(LanguageInterface::STATE_CONFIGURABLE);
        $max_weight = end($configurable_languages)->getWeight();
        $locked_languages = $this->getLanguages(LanguageInterface::STATE_LOCKED);
        // Update locked language weights to maintain the existing order, if
        // necessary.
        if (reset($locked_languages)->getWeight() <= $max_weight) {
            foreach ($locked_languages as $language) {
                // Update system languages weight.
                $max_weight++;
                ConfigurableLanguage::load($language->getId())
                    ->setWeight($max_weight)
                    ->save();
            }
        }
    }
    
    /**
     * {@inheritdoc}
     */
    public function getFallbackCandidates(array $context = []) {
        if ($this->isMultilingual()) {
            $candidates = [];
            if (empty($context['operation']) || $context['operation'] != 'locale_lookup') {
                // If the fallback context is not locale_lookup, initialize the
                // candidates with languages ordered by weight and add
                // LanguageInterface::LANGCODE_NOT_SPECIFIED at the end. Interface
                // translation fallback should only be based on explicit configuration
                // gathered via the alter hooks below.
                $candidates = array_keys($this->getLanguages());
                $candidates[] = LanguageInterface::LANGCODE_NOT_SPECIFIED;
                $candidates = array_combine($candidates, $candidates);
                // The first candidate should always be the desired language if
                // specified.
                if (!empty($context['langcode'])) {
                    $candidates = [
                        $context['langcode'] => $context['langcode'],
                    ] + $candidates;
                }
            }
            // Let other modules hook in and add/change candidates.
            $type = 'language_fallback_candidates';
            $types = [];
            if (!empty($context['operation'])) {
                $types[] = $type . '_' . $context['operation'];
            }
            $types[] = $type;
            $this->moduleHandler
                ->alter($types, $candidates, $context);
        }
        else {
            $candidates = parent::getFallbackCandidates($context);
        }
        return $candidates;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getLanguageSwitchLinks($type, Url $url) {
        if ($this->negotiator) {
            foreach ($this->negotiator
                ->getNegotiationMethods($type) as $method_id => $method) {
                $reflector = new \ReflectionClass($method['class']);
                if ($reflector->implementsInterface('\\Drupal\\language\\LanguageSwitcherInterface')) {
                    $original_languages = $this->negotiatedLanguages;
                    $result = $this->negotiator
                        ->getNegotiationMethodInstance($method_id)
                        ->getLanguageSwitchLinks($this->requestStack
                        ->getCurrentRequest(), $type, $url);
                    if (!empty($result)) {
                        // Allow modules to provide translations for specific links.
                        $this->moduleHandler
                            ->alter('language_switch_links', $result, $type, $url);
                        $result = array_filter($result, function (array $link) : bool {
                            $url = $link['url'] ?? NULL;
                            $language = $link['language'] ?? NULL;
                            if ($language instanceof LanguageInterface) {
                                $this->negotiatedLanguages[LanguageInterface::TYPE_CONTENT] = $language;
                                $this->negotiatedLanguages[LanguageInterface::TYPE_INTERFACE] = $language;
                            }
                            try {
                                return $url instanceof Url && $url->access();
                            } catch (\Exception $e) {
                                return FALSE;
                            }
                        });
                        $this->negotiatedLanguages = $original_languages;
                        $links = (object) [
                            'links' => $result,
                            'method_id' => $method_id,
                        ];
                        break;
                    }
                }
            }
        }
        return $links ?? NULL;
    }
    
    /**
     * Sets the configuration override language.
     *
     * @param \Drupal\Core\Language\LanguageInterface $language
     *   The language to override configuration with.
     *
     * @return $this
     */
    public function setConfigOverrideLanguage(LanguageInterface $language = NULL) {
        $this->configFactoryOverride
            ->setLanguage($language);
        return $this;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getConfigOverrideLanguage() {
        return $this->configFactoryOverride
            ->getLanguage();
    }
    
    /**
     * {@inheritdoc}
     */
    public function getLanguageConfigOverride($langcode, $name) {
        return $this->configFactoryOverride
            ->getOverride($langcode, $name);
    }
    
    /**
     * {@inheritdoc}
     */
    public function getLanguageConfigOverrideStorage($langcode) {
        return $this->configFactoryOverride
            ->getStorage($langcode);
    }
    
    /**
     * {@inheritdoc}
     */
    public function getStandardLanguageListWithoutConfigured() {
        $languages = $this->getLanguages();
        $predefined = $this->getStandardLanguageList();
        foreach ($predefined as $key => $value) {
            if (isset($languages[$key])) {
                unset($predefined[$key]);
                continue;
            }
            $predefined[$key] = new TranslatableMarkup($value[0]);
        }
        natcasesort($predefined);
        return $predefined;
    }
    
    /**
     * {@inheritdoc}
     */
    public function getNegotiatedLanguageMethod($type = LanguageInterface::TYPE_INTERFACE) {
        if (isset($this->negotiatedLanguages[$type]) && isset($this->negotiatedMethods[$type])) {
            return $this->negotiatedMethods[$type];
        }
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
ConfigurableLanguageManager::$configFactory protected property The configuration storage service.
ConfigurableLanguageManager::$configFactoryOverride protected property The language configuration override service.
ConfigurableLanguageManager::$initialized protected property Whether or not the language manager has been initialized.
ConfigurableLanguageManager::$initializing protected property Whether language types are in the process of language initialization.
ConfigurableLanguageManager::$languageTypes protected property Local cache for language type configuration data.
ConfigurableLanguageManager::$languageTypesInfo protected property Local cache for language type information.
ConfigurableLanguageManager::$moduleHandler protected property The module handler service.
ConfigurableLanguageManager::$negotiatedLanguages protected property An array of language objects keyed by language type.
ConfigurableLanguageManager::$negotiatedMethods protected property An array of language negotiation method IDs keyed by language type.
ConfigurableLanguageManager::$negotiator protected property The language negotiator.
ConfigurableLanguageManager::$requestStack protected property The request object.
ConfigurableLanguageManager::getConfigOverrideLanguage public function Gets the current configuration override language. Overrides LanguageManager::getConfigOverrideLanguage
ConfigurableLanguageManager::getCurrentLanguage public function Returns the current language for the given type. Overrides LanguageManager::getCurrentLanguage
ConfigurableLanguageManager::getDefinedLanguageTypes public function Returns all the defined language types including fixed ones. Overrides ConfigurableLanguageManagerInterface::getDefinedLanguageTypes
ConfigurableLanguageManager::getDefinedLanguageTypesInfo public function Returns information about all defined language types. Overrides LanguageManager::getDefinedLanguageTypesInfo
ConfigurableLanguageManager::getFallbackCandidates public function Returns the language fallback candidates for a given context. Overrides LanguageManager::getFallbackCandidates
ConfigurableLanguageManager::getLanguageConfigOverride public function Gets a language config override object. Overrides ConfigurableLanguageManagerInterface::getLanguageConfigOverride
ConfigurableLanguageManager::getLanguageConfigOverrideStorage public function Gets a language configuration override storage object. Overrides ConfigurableLanguageManagerInterface::getLanguageConfigOverrideStorage
ConfigurableLanguageManager::getLanguages public function Returns a list of languages set up on the site. Overrides LanguageManager::getLanguages
ConfigurableLanguageManager::getLanguageSwitchLinks public function Returns the language switch links for the given language type. Overrides LanguageManager::getLanguageSwitchLinks
ConfigurableLanguageManager::getLanguageTypes public function Returns an array of the available language types. Overrides LanguageManager::getLanguageTypes
ConfigurableLanguageManager::getNativeLanguages public function Returns a list of languages set up on the site in their native form. Overrides LanguageManager::getNativeLanguages
ConfigurableLanguageManager::getNegotiatedLanguageMethod public function Gets the negotiated language method ID. Overrides ConfigurableLanguageManagerInterface::getNegotiatedLanguageMethod
ConfigurableLanguageManager::getNegotiator public function Returns the language negotiator. Overrides ConfigurableLanguageManagerInterface::getNegotiator
ConfigurableLanguageManager::getStandardLanguageListWithoutConfigured public function Returns the standard language list excluding already configured languages. Overrides ConfigurableLanguageManagerInterface::getStandardLanguageListWithoutConfigured
ConfigurableLanguageManager::init public function
ConfigurableLanguageManager::isMultilingual public function Returns whether or not the site has more than one language added. Overrides LanguageManager::isMultilingual
ConfigurableLanguageManager::loadLanguageTypesConfiguration protected function Retrieves language types from the configuration storage.
ConfigurableLanguageManager::rebuildServices public static function Rebuild the container to register services needed on multilingual sites. Overrides ConfigurableLanguageManagerInterface::rebuildServices
ConfigurableLanguageManager::reset public function Resets the given language type or all types if none specified. Overrides LanguageManager::reset
ConfigurableLanguageManager::saveLanguageTypesConfiguration public function Stores language types configuration. Overrides ConfigurableLanguageManagerInterface::saveLanguageTypesConfiguration
ConfigurableLanguageManager::setConfigOverrideLanguage public function Sets the configuration override language. Overrides LanguageManager::setConfigOverrideLanguage
ConfigurableLanguageManager::setNegotiator public function Injects the language negotiator. Overrides ConfigurableLanguageManagerInterface::setNegotiator
ConfigurableLanguageManager::updateLockedLanguageWeights public function Updates locked system language weights. Overrides ConfigurableLanguageManagerInterface::updateLockedLanguageWeights
ConfigurableLanguageManager::__construct public function Constructs a new ConfigurableLanguageManager object. Overrides LanguageManager::__construct
DependencySerializationTrait::$_entityStorages protected property
DependencySerializationTrait::$_serviceIds protected property
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
LanguageManager::$defaultLanguage protected property The default language object.
LanguageManager::$definedLanguageTypesInfo protected property Information about all defined language types.
LanguageManager::$languages protected property A static cache of translated language lists.
LanguageManager::filterLanguages protected function Filters the full list of languages based on the value of the flag.
LanguageManager::getDefaultLanguage public function Returns a language object representing the site&#039;s default language. Overrides LanguageManagerInterface::getDefaultLanguage
LanguageManager::getDefaultLockedLanguages public function Returns a list of the default locked languages. Overrides LanguageManagerInterface::getDefaultLockedLanguages
LanguageManager::getLanguage public function Returns a language object from the given language code. Overrides LanguageManagerInterface::getLanguage
LanguageManager::getLanguageName public function Produced the printed name for a language for display. Overrides LanguageManagerInterface::getLanguageName
LanguageManager::getStandardLanguageList public static function Some common languages with their English and native names. Overrides LanguageManagerInterface::getStandardLanguageList
LanguageManager::getUnitedNationsLanguageList public static function The 6 official languages used at the United Nations.
LanguageManager::isLanguageLocked public function Checks whether a language is locked. Overrides LanguageManagerInterface::isLanguageLocked

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.