/** * Sets the request on the language manager. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The Event to process. */ public function onKernelRequestLanguage(GetResponseEvent $event) { if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { $request = $event->getRequest(); $this->negotiator->setCurrentUser($this->currentUser); $this->negotiator->reset(); if ($this->languageManager instanceof ConfigurableLanguageManagerInterface) { $this->languageManager->setNegotiator($this->negotiator); $this->languageManager->setConfigOverrideLanguage($this->languageManager->getCurrentLanguage()); } // After the language manager has initialized, set the default langcode // for the string translations. $langcode = $this->languageManager->getCurrentLanguage()->getId(); $this->translation->setDefaultLangcode($langcode); } }
/** * Initializes the local cache for language path processors. * * @param string $scope * The scope of the processors: "inbound" or "outbound". */ protected function initProcessors($scope) { $interface = '\\Drupal\\Core\\PathProcessor\\' . Unicode::ucfirst($scope) . 'PathProcessorInterface'; $this->processors[$scope] = array(); $weights = []; foreach ($this->languageManager->getLanguageTypes() as $type) { foreach ($this->negotiator->getNegotiationMethods($type) as $method_id => $method) { if (!isset($this->processors[$scope][$method_id])) { $reflector = new \ReflectionClass($method['class']); if ($reflector->implementsInterface($interface)) { $this->processors[$scope][$method_id] = $this->negotiator->getNegotiationMethodInstance($method_id); $weights[$method_id] = $method['weight']; } } } } // Sort the processors list, so that their functions are called in the // order specified by the weight of the methods. uksort($this->processors[$scope], function ($method_id_a, $method_id_b) use($weights) { $a_weight = $weights[$method_id_a]; $b_weight = $weights[$method_id_b]; if ($a_weight == $b_weight) { return 0; } return $a_weight < $b_weight ? -1 : 1; }); }
/** * Initializes the local cache for language path processors. * * @param string $scope * The scope of the processors: "inbound" or "outbound". */ protected function initProcessors($scope) { $interface = '\\Drupal\\Core\\PathProcessor\\' . Unicode::ucfirst($scope) . 'PathProcessorInterface'; $this->processors[$scope] = array(); foreach ($this->languageManager->getLanguageTypes() as $type) { foreach ($this->negotiator->getNegotiationMethods($type) as $method_id => $method) { if (!isset($this->processors[$scope][$method_id])) { $reflector = new \ReflectionClass($method['class']); if ($reflector->implementsInterface($interface)) { $this->processors[$scope][$method_id] = $this->negotiator->getNegotiationMethodInstance($method_id); } } } } }
/** * {@inheritdoc} */ public function getLanguageSwitchLinks($type, Url $url) { $links = FALSE; if ($this->negotiator) { foreach ($this->negotiator->getNegotiationMethods($type) as $method_id => $method) { $reflector = new \ReflectionClass($method['class']); if ($reflector->implementsInterface('\\Drupal\\language\\LanguageSwitcherInterface')) { $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, $path); $links = (object) array('links' => $result, 'method_id' => $method_id); break; } } } } return $links; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $configurable_types = $form['#language_types']; $stored_values = $this->languageTypes->get('configurable'); $customized = array(); $method_weights_type = array(); foreach ($configurable_types as $type) { $customized[$type] = in_array($type, $stored_values); $method_weights = array(); $enabled_methods = $form_state->getValue(array($type, 'enabled')); $enabled_methods[LanguageNegotiationSelected::METHOD_ID] = TRUE; $method_weights_input = $form_state->getValue(array($type, 'weight')); if ($form_state->hasValue(array($type, 'configurable'))) { $customized[$type] = !$form_state->isValueEmpty(array($type, 'configurable')); } foreach ($method_weights_input as $method_id => $weight) { if ($enabled_methods[$method_id]) { $method_weights[$method_id] = $weight; } } $method_weights_type[$type] = $method_weights; $this->languageTypes->set('negotiation.' . $type . '.method_weights', $method_weights_input)->save(); } // Update non-configurable language types and the related language // negotiation configuration. $this->negotiator->updateConfiguration(array_keys(array_filter($customized))); // Update the language negotiations after setting the configurability. foreach ($method_weights_type as $type => $method_weights) { $this->negotiator->saveConfiguration($type, $method_weights); } // Clear block definitions cache since the available blocks and their names // may have been changed based on the configurable types. if ($this->blockStorage) { // If there is an active language switcher for a language type that has // been made not configurable, deactivate it first. $non_configurable = array_keys(array_diff($customized, array_filter($customized))); $this->disableLanguageSwitcher($non_configurable); } $this->blockManager->clearCachedDefinitions(); $form_state->setRedirect('language.negotiation'); drupal_set_message($this->t('Language detection configuration saved.')); }
/** * Causes the container to be rebuilt on the next request. * * This event subscriber assumes that the new default langcode and old default * langcode are valid langcodes. If the schema definition of either * system.site:default_langcode or language.negotiation::url.prefixes changes * then this event must be changed to work with both the old and new schema * definition so this event is update safe. * * @param ConfigCrudEvent $event * The configuration event. */ public function onConfigSave(ConfigCrudEvent $event) { $saved_config = $event->getConfig(); if ($saved_config->getName() == 'system.site' && $event->isChanged('default_langcode')) { $new_default_langcode = $saved_config->get('default_langcode'); $default_language = $this->configFactory->get('language.entity.' . $new_default_langcode); // During an import the language might not exist yet. if (!$default_language->isNew()) { $this->languageDefault->set(new Language($default_language->get())); $this->languageManager->reset(); // Directly update language negotiation settings instead of calling // language_negotiation_url_prefixes_update() to ensure that the code // obeys the hook_update_N() restrictions. $negotiation_config = $this->configFactory->getEditable('language.negotiation'); $negotiation_changed = FALSE; $url_prefixes = $negotiation_config->get('url.prefixes'); $old_default_langcode = $saved_config->getOriginal('default_langcode'); if (empty($url_prefixes[$old_default_langcode])) { $negotiation_config->set('url.prefixes.' . $old_default_langcode, $old_default_langcode); $negotiation_changed = TRUE; } if (empty($url_prefixes[$new_default_langcode])) { $negotiation_config->set('url.prefixes.' . $new_default_langcode, ''); $negotiation_changed = TRUE; } if ($negotiation_changed) { $negotiation_config->save(TRUE); } } // Trigger a container rebuild on the next request by invalidating it. ConfigurableLanguageManager::rebuildServices(); } elseif ($saved_config->getName() == 'language.types' && $event->isChanged('negotiation')) { // If the negotiation configuration changed the language negotiator and // the language path processor have to be reset so that they regenerate // the method instances and also sort them accordingly to the new config. $this->languageNegotiator->reset(); if (isset($this->pathProcessorLanguage)) { $this->pathProcessorLanguage->reset(); } } }