Initial Drupal 11 with DDEV setup
This commit is contained in:
128
web/core/modules/language/src/Plugin/Block/LanguageBlock.php
Normal file
128
web/core/modules/language/src/Plugin/Block/LanguageBlock.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Block\Attribute\Block;
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Path\PathMatcherInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Drupal\language\Plugin\Derivative\LanguageBlock as LanguageBlockDeriver;
|
||||
|
||||
/**
|
||||
* Provides a 'Language switcher' block.
|
||||
*/
|
||||
#[Block(
|
||||
id: "language_block",
|
||||
admin_label: new TranslatableMarkup("Language switcher"),
|
||||
category: new TranslatableMarkup("System"),
|
||||
deriver: LanguageBlockDeriver::class
|
||||
)]
|
||||
class LanguageBlock extends BlockBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The path matcher.
|
||||
*
|
||||
* @var \Drupal\Core\Path\PathMatcherInterface
|
||||
*/
|
||||
protected $pathMatcher;
|
||||
|
||||
/**
|
||||
* Constructs a LanguageBlock object.
|
||||
*
|
||||
* @param array $configuration
|
||||
* A configuration array containing information about the plugin instance.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Path\PathMatcherInterface $path_matcher
|
||||
* The path matcher.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, LanguageManagerInterface $language_manager, PathMatcherInterface $path_matcher) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->languageManager = $language_manager;
|
||||
$this->pathMatcher = $path_matcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('language_manager'),
|
||||
$container->get('path.matcher')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function blockAccess(AccountInterface $account) {
|
||||
$access = $this->languageManager->isMultilingual() ? AccessResult::allowed() : AccessResult::forbidden();
|
||||
return $access->addCacheTags(['config:configurable_language_list']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
$build = [];
|
||||
$type = $this->getDerivativeId();
|
||||
$route_match = \Drupal::routeMatch();
|
||||
// If there is no route match, for example when creating blocks on 404 pages
|
||||
// for logged-in users with big_pipe enabled using the front page instead.
|
||||
if ($this->pathMatcher->isFrontPage() || !$route_match->getRouteObject()) {
|
||||
// We are skipping the route match on both 404 and front page.
|
||||
// Example: If on front page, there is no route match like when creating
|
||||
// blocks on 404 pages for logged-in users with big_pipe enabled, use the
|
||||
// front page.
|
||||
$url = Url::fromRoute('<front>');
|
||||
}
|
||||
else {
|
||||
$url = Url::fromRouteMatch($route_match);
|
||||
}
|
||||
$links = $this->languageManager->getLanguageSwitchLinks($type, $url);
|
||||
|
||||
if (isset($links->links)) {
|
||||
$build = [
|
||||
'#theme' => 'links__language_block',
|
||||
'#links' => $links->links,
|
||||
'#attributes' => [
|
||||
'class' => [
|
||||
"language-switcher-{$links->method_id}",
|
||||
],
|
||||
],
|
||||
'#set_active_class' => TRUE,
|
||||
];
|
||||
}
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo Make cacheable in https://www.drupal.org/node/2232375.
|
||||
*/
|
||||
public function getCacheMaxAge() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
155
web/core/modules/language/src/Plugin/Condition/Language.php
Normal file
155
web/core/modules/language/src/Plugin/Condition/Language.php
Normal file
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\Condition;
|
||||
|
||||
use Drupal\Core\Condition\Attribute\Condition;
|
||||
use Drupal\Core\Condition\ConditionPluginBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Plugin\Context\ContextDefinition;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Provides a 'Language' condition.
|
||||
*/
|
||||
#[Condition(
|
||||
id: "language",
|
||||
label: new TranslatableMarkup("Language"),
|
||||
context_definitions: [
|
||||
"language" => new ContextDefinition(
|
||||
data_type: "language",
|
||||
label: new TranslatableMarkup("Language"),
|
||||
),
|
||||
]
|
||||
)]
|
||||
class Language extends ConditionPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The Language manager.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* Creates a new Language instance.
|
||||
*
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param array $configuration
|
||||
* The plugin configuration, i.e. an array with configuration values keyed
|
||||
* by configuration option name. The special key 'context' may be used to
|
||||
* initialize the defined contexts by setting it to an array of context
|
||||
* values keyed by context names.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID for the plugin instance.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin implementation definition.
|
||||
*/
|
||||
public function __construct(LanguageManagerInterface $language_manager, array $configuration, $plugin_id, $plugin_definition) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->languageManager = $language_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$container->get('language_manager'),
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
if ($this->languageManager->isMultilingual()) {
|
||||
// Fetch languages.
|
||||
$languages = $this->languageManager->getLanguages();
|
||||
$langcodes_options = [];
|
||||
foreach ($languages as $language) {
|
||||
$langcodes_options[$language->getId()] = $language->getName();
|
||||
}
|
||||
$form['langcodes'] = [
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => $this->t('Language selection'),
|
||||
'#default_value' => $this->configuration['langcodes'],
|
||||
'#options' => $langcodes_options,
|
||||
'#description' => $this->t('Select languages to enforce. If none are selected, all languages will be allowed.'),
|
||||
];
|
||||
}
|
||||
else {
|
||||
$form['langcodes'] = [
|
||||
'#type' => 'value',
|
||||
'#default_value' => $this->configuration['langcodes'],
|
||||
];
|
||||
}
|
||||
return parent::buildConfigurationForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->configuration['langcodes'] = array_filter($form_state->getValue('langcodes'));
|
||||
parent::submitConfigurationForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function summary() {
|
||||
$language_list = $this->languageManager->getLanguages(LanguageInterface::STATE_ALL);
|
||||
$selected = $this->configuration['langcodes'];
|
||||
// Reduce the language list to an array of language names.
|
||||
$language_names = array_reduce($language_list, function ($result, $item) use ($selected) {
|
||||
// If the current item of the $language_list array is one of the selected
|
||||
// languages, add it to the $results array.
|
||||
if (!empty($selected[$item->getId()])) {
|
||||
$result[$item->getId()] = $item->getName();
|
||||
}
|
||||
return $result;
|
||||
}, []);
|
||||
|
||||
// If we have more than one language selected, separate them by commas.
|
||||
if (count($this->configuration['langcodes']) > 1) {
|
||||
$languages = implode(', ', $language_names);
|
||||
}
|
||||
else {
|
||||
// If we have just one language just grab the only present value.
|
||||
$languages = array_pop($language_names);
|
||||
}
|
||||
if (!empty($this->configuration['negate'])) {
|
||||
return $this->t('The language is not @languages.', ['@languages' => $languages]);
|
||||
}
|
||||
return $this->t('The language is @languages.', ['@languages' => $languages]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function evaluate() {
|
||||
if (empty($this->configuration['langcodes']) && !$this->isNegated()) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$language = $this->getContextValue('language');
|
||||
// Language visibility settings.
|
||||
return !empty($this->configuration['langcodes'][$language->getId()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return ['langcodes' => []] + parent::defaultConfiguration();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\Derivative;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\language\ConfigurableLanguageManagerInterface;
|
||||
|
||||
/**
|
||||
* Provides language switcher block plugin definitions for all languages.
|
||||
*/
|
||||
class LanguageBlock extends DeriverBase {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$language_manager = \Drupal::languageManager();
|
||||
|
||||
if ($language_manager instanceof ConfigurableLanguageManagerInterface) {
|
||||
$info = $language_manager->getDefinedLanguageTypesInfo();
|
||||
$configurable_types = $language_manager->getLanguageTypes();
|
||||
foreach ($configurable_types as $type) {
|
||||
$this->derivatives[$type] = $base_plugin_definition;
|
||||
$this->derivatives[$type]['admin_label'] = $this->t('Language switcher (@type)', ['@type' => $info[$type]['name']]);
|
||||
}
|
||||
// If there is just one configurable type then change the title of the
|
||||
// block.
|
||||
if (count($configurable_types) == 1) {
|
||||
$this->derivatives[reset($configurable_types)]['admin_label'] = $this->t('Language switcher');
|
||||
}
|
||||
}
|
||||
|
||||
return parent::getDerivativeDefinitions($base_plugin_definition);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\LanguageNegotiation;
|
||||
|
||||
use Drupal\Component\Utility\UserAgent;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\language\Attribute\LanguageNegotiation;
|
||||
use Drupal\language\LanguageNegotiationMethodBase;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Class for identifying language from the browser Accept-language HTTP header.
|
||||
*/
|
||||
#[LanguageNegotiation(
|
||||
id: LanguageNegotiationBrowser::METHOD_ID,
|
||||
name: new TranslatableMarkup('Browser'),
|
||||
weight: -2,
|
||||
description: new TranslatableMarkup("Language from the browser's language settings."),
|
||||
config_route_name: 'language.negotiation_browser'
|
||||
)]
|
||||
class LanguageNegotiationBrowser extends LanguageNegotiationMethodBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The language negotiation method id.
|
||||
*/
|
||||
const METHOD_ID = 'language-browser';
|
||||
|
||||
/**
|
||||
* The page cache disabling policy.
|
||||
*
|
||||
* @var \Drupal\Core\PageCache\ResponsePolicy\KillSwitch
|
||||
*/
|
||||
protected $pageCacheKillSwitch;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
$instance = new static();
|
||||
$instance->pageCacheKillSwitch = $container->get('page_cache_kill_switch');
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode(?Request $request = NULL) {
|
||||
$langcode = NULL;
|
||||
|
||||
if ($this->languageManager && $request && $request->server->get('HTTP_ACCEPT_LANGUAGE')) {
|
||||
$http_accept_language = $request->server->get('HTTP_ACCEPT_LANGUAGE');
|
||||
$langcodes = array_keys($this->languageManager->getLanguages());
|
||||
$mappings = $this->config->get('language.mappings')->get('map');
|
||||
$langcode = UserAgent::getBestMatchingLangcode($http_accept_language, $langcodes, $mappings);
|
||||
}
|
||||
|
||||
// Internal page cache with multiple languages and browser negotiation
|
||||
// could lead to wrong cached sites. Therefore disabling the internal page
|
||||
// cache.
|
||||
// @todo Solve more elegantly in https://www.drupal.org/node/2430335.
|
||||
$this->pageCacheKillSwitch->trigger();
|
||||
|
||||
return $langcode;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\LanguageNegotiation;
|
||||
|
||||
use Drupal\Core\Entity\ContentEntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\language\Attribute\LanguageNegotiation;
|
||||
use Drupal\language\LanguageNegotiationMethodBase;
|
||||
use Drupal\language\LanguageSwitcherInterface;
|
||||
use Drupal\Core\Routing\RouteObjectInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Class for identifying the content translation language.
|
||||
*/
|
||||
#[LanguageNegotiation(
|
||||
id: LanguageNegotiationContentEntity::METHOD_ID,
|
||||
name: new TranslatableMarkup('Content language'),
|
||||
types: [LanguageInterface::TYPE_CONTENT],
|
||||
weight: -9,
|
||||
description: new TranslatableMarkup("Determines the content language from the request parameter named 'language_content_entity'.")
|
||||
)]
|
||||
class LanguageNegotiationContentEntity extends LanguageNegotiationMethodBase implements OutboundPathProcessorInterface, LanguageSwitcherInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The language negotiation method ID.
|
||||
*/
|
||||
const METHOD_ID = 'language-content-entity';
|
||||
|
||||
/**
|
||||
* The query string parameter.
|
||||
*/
|
||||
const QUERY_PARAMETER = 'language_content_entity';
|
||||
|
||||
/**
|
||||
* A list of all the link paths of enabled content entities.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $contentEntityPaths;
|
||||
|
||||
/**
|
||||
* Static cache for the language negotiation order check.
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @see \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity::hasLowerLanguageNegotiationWeight()
|
||||
*/
|
||||
protected $hasLowerLanguageNegotiationWeightResult;
|
||||
|
||||
/**
|
||||
* Static cache of outbound route paths per request.
|
||||
*
|
||||
* @var \SplObjectStorage
|
||||
*/
|
||||
protected $paths;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a new LanguageNegotiationContentEntity instance.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->paths = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static($container->get('entity_type.manager'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode(?Request $request = NULL) {
|
||||
if ($request === NULL || $this->languageManager === NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$langcode = $request->query->get(static::QUERY_PARAMETER);
|
||||
|
||||
$language_enabled = array_key_exists($langcode, $this->languageManager->getLanguages());
|
||||
return $language_enabled ? $langcode : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processOutbound($path, &$options = [], ?Request $request = NULL, ?BubbleableMetadata $bubbleable_metadata = NULL) {
|
||||
// If appropriate, process outbound to add a query parameter to the URL and
|
||||
// remove the language option, so that URL negotiator does not rewrite the
|
||||
// URL.
|
||||
|
||||
// First, check if processing conditions are met.
|
||||
if (!($request && !empty($options['route']) && $this->hasLowerLanguageNegotiationWeight() && $this->meetsContentEntityRoutesCondition($options['route'], $request))) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
if (isset($options['language']) || $langcode = $this->getLangcode($request)) {
|
||||
// If the language option is set, unset it, so that the URL language
|
||||
// negotiator does not rewrite the URL.
|
||||
if (isset($options['language'])) {
|
||||
$langcode = $options['language']->getId();
|
||||
unset($options['language']);
|
||||
}
|
||||
|
||||
if (!isset($options['query'][static::QUERY_PARAMETER])) {
|
||||
$options['query'][static::QUERY_PARAMETER] = $langcode;
|
||||
}
|
||||
|
||||
if ($bubbleable_metadata) {
|
||||
// Cached URLs that have been processed by this outbound path
|
||||
// processor must be:
|
||||
$bubbleable_metadata
|
||||
// - varied by the content language query parameter.
|
||||
->addCacheContexts(['url.query_args:' . static::QUERY_PARAMETER]);
|
||||
}
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLanguageSwitchLinks(Request $request, $type, Url $url) {
|
||||
$links = [];
|
||||
$query = [];
|
||||
parse_str($request->getQueryString() ?? '', $query);
|
||||
|
||||
foreach ($this->languageManager->getNativeLanguages() as $language) {
|
||||
$langcode = $language->getId();
|
||||
$query[static::QUERY_PARAMETER] = $langcode;
|
||||
$links[$langcode] = [
|
||||
'url' => $url,
|
||||
'title' => $language->getName(),
|
||||
'attributes' => ['class' => ['language-link']],
|
||||
'query' => $query,
|
||||
];
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if content entity language negotiator has higher priority.
|
||||
*
|
||||
* The content entity language negotiator having higher priority than the URL
|
||||
* language negotiator, is a criteria in
|
||||
* \Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationContentEntity::processOutbound().
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the content entity language negotiator has higher priority than
|
||||
* the URL language negotiator, FALSE otherwise.
|
||||
*/
|
||||
protected function hasLowerLanguageNegotiationWeight() {
|
||||
if (!isset($this->hasLowerLanguageNegotiationWeightResult)) {
|
||||
// Only run if the LanguageNegotiationContentEntity outbound function is
|
||||
// being executed before the outbound function of LanguageNegotiationUrl.
|
||||
$content_method_weights = $this->config->get('language.types')->get('negotiation.language_content.enabled') ?: [];
|
||||
|
||||
// Check if the content language is configured to be dependent on the
|
||||
// URL negotiator directly or indirectly over the interface negotiator.
|
||||
if (isset($content_method_weights[LanguageNegotiationUrl::METHOD_ID]) && ($content_method_weights[static::METHOD_ID] > $content_method_weights[LanguageNegotiationUrl::METHOD_ID])) {
|
||||
$this->hasLowerLanguageNegotiationWeightResult = FALSE;
|
||||
}
|
||||
else {
|
||||
$check_interface_method = FALSE;
|
||||
if (isset($content_method_weights[LanguageNegotiationUI::METHOD_ID])) {
|
||||
$interface_method_weights = $this->config->get('language.types')->get('negotiation.language_interface.enabled') ?: [];
|
||||
$check_interface_method = isset($interface_method_weights[LanguageNegotiationUrl::METHOD_ID]);
|
||||
}
|
||||
if ($check_interface_method) {
|
||||
$max_weight = $content_method_weights[LanguageNegotiationUI::METHOD_ID];
|
||||
$max_weight = isset($content_method_weights[LanguageNegotiationUrl::METHOD_ID]) ? max($max_weight, $content_method_weights[LanguageNegotiationUrl::METHOD_ID]) : $max_weight;
|
||||
}
|
||||
else {
|
||||
$max_weight = $content_method_weights[LanguageNegotiationUrl::METHOD_ID] ?? PHP_INT_MAX;
|
||||
}
|
||||
|
||||
$this->hasLowerLanguageNegotiationWeightResult = $content_method_weights[static::METHOD_ID] < $max_weight;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->hasLowerLanguageNegotiationWeightResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if content entity route condition is met.
|
||||
*
|
||||
* Requirements: currently being on a content entity route and processing
|
||||
* outbound URL pointing to the same content entity.
|
||||
*
|
||||
* @param \Symfony\Component\Routing\Route $outbound_route
|
||||
* The route object for the current outbound URL being processed.
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The HttpRequest object representing the current request.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the content entity route condition is met, FALSE otherwise.
|
||||
*/
|
||||
protected function meetsContentEntityRoutesCondition(Route $outbound_route, Request $request) {
|
||||
$outbound_path_pattern = $outbound_route->getPath();
|
||||
$storage = $this->paths[$request] ?? [];
|
||||
if (!isset($storage[$outbound_path_pattern])) {
|
||||
$storage[$outbound_path_pattern] = FALSE;
|
||||
|
||||
// Check if the outbound route points to the current entity.
|
||||
if ($content_entity_type_id_for_current_route = $this->getContentEntityTypeIdForCurrentRequest($request)) {
|
||||
if (!empty($this->getContentEntityPaths()[$outbound_path_pattern]) && $content_entity_type_id_for_current_route == $this->getContentEntityPaths()[$outbound_path_pattern]) {
|
||||
$storage[$outbound_path_pattern] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
$this->paths[$request] = $storage;
|
||||
}
|
||||
|
||||
return $storage[$outbound_path_pattern];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content entity type ID from the current request for the route.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The HttpRequest object representing the current request.
|
||||
*
|
||||
* @return string
|
||||
* The entity type ID for the route from the request.
|
||||
*/
|
||||
protected function getContentEntityTypeIdForCurrentRequest(Request $request) {
|
||||
$content_entity_type_id_for_current_route = '';
|
||||
|
||||
if ($current_route = $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)) {
|
||||
$current_route_path = $current_route->getPath();
|
||||
$content_entity_type_id_for_current_route = $this->getContentEntityPaths()[$current_route_path] ?? '';
|
||||
}
|
||||
|
||||
return $content_entity_type_id_for_current_route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the paths for the link templates of all content entities.
|
||||
*
|
||||
* @return array
|
||||
* An array of all content entity type IDs, keyed by the corresponding link
|
||||
* template paths.
|
||||
*/
|
||||
protected function getContentEntityPaths() {
|
||||
if (!isset($this->contentEntityPaths)) {
|
||||
$this->contentEntityPaths = [];
|
||||
$entity_types = $this->entityTypeManager->getDefinitions();
|
||||
foreach ($entity_types as $entity_type_id => $entity_type) {
|
||||
if ($entity_type->entityClassImplements(ContentEntityInterface::class)) {
|
||||
$entity_paths = array_fill_keys($entity_type->getLinkTemplates(), $entity_type_id);
|
||||
$this->contentEntityPaths = array_merge($this->contentEntityPaths, $entity_paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->contentEntityPaths;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\LanguageNegotiation;
|
||||
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\language\Attribute\LanguageNegotiation;
|
||||
use Drupal\language\LanguageNegotiationMethodBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Class for identifying language from a selected language.
|
||||
*/
|
||||
#[LanguageNegotiation(
|
||||
id: LanguageNegotiationSelected::METHOD_ID,
|
||||
name: new TranslatableMarkup('Selected language'),
|
||||
weight: 12,
|
||||
description: new TranslatableMarkup("Language based on a selected language."),
|
||||
config_route_name: 'language.negotiation_selected'
|
||||
)]
|
||||
class LanguageNegotiationSelected extends LanguageNegotiationMethodBase {
|
||||
|
||||
/**
|
||||
* The language negotiation method id.
|
||||
*/
|
||||
const METHOD_ID = 'language-selected';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode(?Request $request = NULL) {
|
||||
$langcode = NULL;
|
||||
|
||||
if ($this->languageManager) {
|
||||
$langcode = $this->config->get('language.negotiation')->get('selected_langcode');
|
||||
}
|
||||
|
||||
return $langcode;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\LanguageNegotiation;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\language\Attribute\LanguageNegotiation;
|
||||
use Drupal\language\LanguageNegotiationMethodBase;
|
||||
use Drupal\language\LanguageSwitcherInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
/**
|
||||
* Identify language from a request/session parameter.
|
||||
*/
|
||||
#[LanguageNegotiation(
|
||||
id: LanguageNegotiationSession::METHOD_ID,
|
||||
name: new TranslatableMarkup('Session'),
|
||||
weight: -6,
|
||||
description: new TranslatableMarkup("Language from a request/session parameter."),
|
||||
config_route_name: 'language.negotiation_session'
|
||||
)]
|
||||
class LanguageNegotiationSession extends LanguageNegotiationMethodBase implements OutboundPathProcessorInterface, LanguageSwitcherInterface, ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* Flag used to determine whether query rewriting is active.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $queryRewrite;
|
||||
|
||||
/**
|
||||
* The query parameter name to rewrite.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $queryParam;
|
||||
|
||||
/**
|
||||
* The query parameter value to be set.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $queryValue;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* The language negotiation method id.
|
||||
*/
|
||||
const METHOD_ID = 'language-session';
|
||||
|
||||
/**
|
||||
* Constructs a LanguageNegotiationSession object.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack.
|
||||
*/
|
||||
public function __construct(RequestStack $request_stack) {
|
||||
$this->requestStack = $request_stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$container->get('request_stack')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode(?Request $request = NULL) {
|
||||
$config = $this->config->get('language.negotiation')->get('session');
|
||||
if (($param = $config['parameter']) && $request) {
|
||||
if ($request->query->has($param)) {
|
||||
return $request->query->get($param);
|
||||
}
|
||||
if ($request->getSession()->has($param)) {
|
||||
return $request->getSession()->get($param);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function persist(LanguageInterface $language) {
|
||||
// We need to update the session parameter with the request value only if we
|
||||
// have an authenticated user.
|
||||
$langcode = $language->getId();
|
||||
if ($langcode && $this->languageManager) {
|
||||
$languages = $this->languageManager->getLanguages();
|
||||
if ($this->currentUser->isAuthenticated() && isset($languages[$langcode])) {
|
||||
$config = $this->config->get('language.negotiation')->get('session');
|
||||
$this->requestStack->getCurrentRequest()->getSession()->set($config['parameter'], $langcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processOutbound($path, &$options = [], ?Request $request = NULL, ?BubbleableMetadata $bubbleable_metadata = NULL) {
|
||||
if ($request) {
|
||||
// The following values are not supposed to change during a single page
|
||||
// request processing.
|
||||
if (!isset($this->queryRewrite)) {
|
||||
if ($this->currentUser->isAnonymous()) {
|
||||
$languages = $this->languageManager->getLanguages();
|
||||
$config = $this->config->get('language.negotiation')->get('session');
|
||||
$this->queryParam = $config['parameter'];
|
||||
$this->queryValue = $request->query->has($this->queryParam) ? $request->query->get($this->queryParam) : NULL;
|
||||
$this->queryRewrite = isset($languages[$this->queryValue]);
|
||||
}
|
||||
else {
|
||||
$this->queryRewrite = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// If the user is anonymous, the user language negotiation method is
|
||||
// enabled, and the corresponding option has been set, we must preserve
|
||||
// any explicit user language preference even with cookies disabled.
|
||||
if ($this->queryRewrite) {
|
||||
if (!isset($options['query'][$this->queryParam])) {
|
||||
$options['query'][$this->queryParam] = $this->queryValue;
|
||||
}
|
||||
if ($bubbleable_metadata) {
|
||||
// Cached URLs that have been processed by this outbound path
|
||||
// processor must be:
|
||||
$bubbleable_metadata
|
||||
// - invalidated when the language negotiation config changes, since
|
||||
// another query parameter may be used to determine the language.
|
||||
->addCacheTags($this->config->get('language.negotiation')->getCacheTags())
|
||||
// - varied by the configured query parameter.
|
||||
->addCacheContexts(['url.query_args:' . $this->queryParam]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLanguageSwitchLinks(Request $request, $type, Url $url) {
|
||||
$links = [];
|
||||
$query = [];
|
||||
parse_str($request->getQueryString() ?? '', $query);
|
||||
$config = $this->config->get('language.negotiation')->get('session');
|
||||
$param = $config['parameter'];
|
||||
$language_query = $request->getSession()->has($param) ? $request->getSession()->get($param) : $this->languageManager->getCurrentLanguage($type)->getId();
|
||||
|
||||
foreach ($this->languageManager->getNativeLanguages() as $language) {
|
||||
$langcode = $language->getId();
|
||||
$links[$langcode] = [
|
||||
// We need to clone the $url object to avoid using the same one for all
|
||||
// links. When the links are rendered, options are set on the $url
|
||||
// object, so if we use the same one, they would be set for all links.
|
||||
'url' => clone $url,
|
||||
'title' => $language->getName(),
|
||||
'attributes' => ['class' => ['language-link']],
|
||||
'query' => $query,
|
||||
];
|
||||
if ($language_query != $langcode) {
|
||||
$links[$langcode]['query'][$param] = $langcode;
|
||||
}
|
||||
else {
|
||||
$links[$langcode]['attributes']['class'][] = 'session-active';
|
||||
}
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\LanguageNegotiation;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\language\Attribute\LanguageNegotiation;
|
||||
use Drupal\language\LanguageNegotiationMethodBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Identifies the language from the interface text language selected for page.
|
||||
*/
|
||||
#[LanguageNegotiation(
|
||||
id: LanguageNegotiationUI::METHOD_ID,
|
||||
name: new TranslatableMarkup('Interface'),
|
||||
types: [LanguageInterface::TYPE_CONTENT],
|
||||
weight: 9,
|
||||
description: new TranslatableMarkup("Use the detected interface language.")
|
||||
)]
|
||||
class LanguageNegotiationUI extends LanguageNegotiationMethodBase {
|
||||
|
||||
/**
|
||||
* The language negotiation method id.
|
||||
*/
|
||||
const METHOD_ID = 'language-interface';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode(?Request $request = NULL) {
|
||||
return $this->languageManager ? $this->languageManager->getCurrentLanguage()->getId() : NULL;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\LanguageNegotiation;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
|
||||
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\language\Attribute\LanguageNegotiation;
|
||||
use Drupal\language\LanguageNegotiationMethodBase;
|
||||
use Drupal\language\LanguageSwitcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Class for identifying language via URL prefix or domain.
|
||||
*/
|
||||
#[LanguageNegotiation(
|
||||
id: LanguageNegotiationUrl::METHOD_ID,
|
||||
name: new TranslatableMarkup('URL'),
|
||||
types: [LanguageInterface::TYPE_INTERFACE,
|
||||
LanguageInterface::TYPE_CONTENT,
|
||||
LanguageInterface::TYPE_URL,
|
||||
],
|
||||
weight: -8,
|
||||
description: new TranslatableMarkup("Language from the URL (Path prefix or domain)."),
|
||||
config_route_name: 'language.negotiation_url'
|
||||
)]
|
||||
class LanguageNegotiationUrl extends LanguageNegotiationMethodBase implements InboundPathProcessorInterface, OutboundPathProcessorInterface, LanguageSwitcherInterface {
|
||||
|
||||
/**
|
||||
* The language negotiation method id.
|
||||
*/
|
||||
const METHOD_ID = 'language-url';
|
||||
|
||||
/**
|
||||
* URL language negotiation: use the path prefix as URL language indicator.
|
||||
*/
|
||||
const CONFIG_PATH_PREFIX = 'path_prefix';
|
||||
|
||||
/**
|
||||
* URL language negotiation: use the domain as URL language indicator.
|
||||
*/
|
||||
const CONFIG_DOMAIN = 'domain';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode(?Request $request = NULL) {
|
||||
$langcode = NULL;
|
||||
|
||||
if ($request && $this->languageManager) {
|
||||
$languages = $this->languageManager->getLanguages();
|
||||
$config = $this->config->get('language.negotiation')->get('url');
|
||||
|
||||
switch ($config['source']) {
|
||||
case LanguageNegotiationUrl::CONFIG_PATH_PREFIX:
|
||||
$request_path = urldecode(trim($request->getPathInfo(), '/'));
|
||||
$path_args = explode('/', $request_path);
|
||||
$prefix = array_shift($path_args);
|
||||
|
||||
// Search prefix within added languages.
|
||||
$negotiated_language = FALSE;
|
||||
foreach ($languages as $language) {
|
||||
if (isset($config['prefixes'][$language->getId()]) && $config['prefixes'][$language->getId()] == $prefix) {
|
||||
$negotiated_language = $language;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($negotiated_language) {
|
||||
$langcode = $negotiated_language->getId();
|
||||
}
|
||||
break;
|
||||
|
||||
case LanguageNegotiationUrl::CONFIG_DOMAIN:
|
||||
// Get only the host, not the port.
|
||||
$http_host = $request->getHost();
|
||||
foreach ($languages as $language) {
|
||||
// Skip the check if the language doesn't have a domain.
|
||||
if (!empty($config['domains'][$language->getId()])) {
|
||||
// Ensure that there is exactly one protocol in the URL when
|
||||
// checking the hostname.
|
||||
$host = 'http://' . str_replace(['http://', 'https://'], '', $config['domains'][$language->getId()]);
|
||||
$host = parse_url($host, PHP_URL_HOST);
|
||||
if ($http_host == $host) {
|
||||
$langcode = $language->getId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $langcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processInbound($path, Request $request) {
|
||||
$config = $this->config->get('language.negotiation')->get('url');
|
||||
|
||||
if ($config['source'] == LanguageNegotiationUrl::CONFIG_PATH_PREFIX) {
|
||||
$parts = explode('/', trim($path, '/'));
|
||||
$prefix = array_shift($parts);
|
||||
|
||||
// Search prefix within added languages.
|
||||
foreach ($this->languageManager->getLanguages() as $language) {
|
||||
if (isset($config['prefixes'][$language->getId()]) && $config['prefixes'][$language->getId()] == $prefix) {
|
||||
// Rebuild $path with the language removed.
|
||||
$path = '/' . implode('/', $parts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function processOutbound($path, &$options = [], ?Request $request = NULL, ?BubbleableMetadata $bubbleable_metadata = NULL) {
|
||||
$url_scheme = 'http';
|
||||
$port = 80;
|
||||
if ($request) {
|
||||
$url_scheme = $request->getScheme();
|
||||
$port = $request->getPort();
|
||||
}
|
||||
$languages = array_flip(array_keys($this->languageManager->getLanguages()));
|
||||
// Language can be passed as an option, or we go for current URL language.
|
||||
if (!isset($options['language']) || ($options['language'] instanceof LanguageInterface && $options['language']->getId() == LanguageInterface::LANGCODE_NOT_SPECIFIED)) {
|
||||
$language_url = $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_URL);
|
||||
$options['language'] = $language_url;
|
||||
}
|
||||
// We allow only added languages here.
|
||||
elseif (!is_object($options['language']) || !isset($languages[$options['language']->getId()])) {
|
||||
return $path;
|
||||
}
|
||||
$config = $this->config->get('language.negotiation')->get('url');
|
||||
if ($config['source'] == LanguageNegotiationUrl::CONFIG_PATH_PREFIX) {
|
||||
if (is_object($options['language']) && !empty($config['prefixes'][$options['language']->getId()])) {
|
||||
$options['prefix'] = $config['prefixes'][$options['language']->getId()] . '/';
|
||||
if ($bubbleable_metadata) {
|
||||
$bubbleable_metadata->addCacheContexts(['languages:' . LanguageInterface::TYPE_URL]);
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($config['source'] == LanguageNegotiationUrl::CONFIG_DOMAIN) {
|
||||
if (is_object($options['language']) && !empty($config['domains'][$options['language']->getId()])) {
|
||||
|
||||
// Check if the base URLs match, return early if they do.
|
||||
if (isset($options['base_url']) && $request && $request->getHost() === parse_url($options['base_url'], PHP_URL_HOST)) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
// Save the original base URL. If it contains a port, we need to
|
||||
// retain it below.
|
||||
if (!empty($options['base_url'])) {
|
||||
// The colon in the URL scheme messes up the port checking below.
|
||||
$normalized_base_url = str_replace(['https://', 'http://'], '', $options['base_url']);
|
||||
}
|
||||
|
||||
// Ask for an absolute URL with our modified base URL only if the domain
|
||||
// is different from the current request domain.
|
||||
if ($request && $request->getHost() !== $config['domains'][$options['language']->getId()]) {
|
||||
$options['absolute'] = TRUE;
|
||||
$options['base_url'] = $url_scheme . '://' . $config['domains'][$options['language']->getId()];
|
||||
|
||||
// In case either the original base URL or the HTTP host contains a
|
||||
// port, retain it.
|
||||
if (isset($normalized_base_url) && str_contains($normalized_base_url, ':')) {
|
||||
[, $port] = explode(':', $normalized_base_url);
|
||||
$options['base_url'] .= ':' . $port;
|
||||
}
|
||||
elseif (($url_scheme == 'http' && $port != 80) || ($url_scheme == 'https' && $port != 443)) {
|
||||
$options['base_url'] .= ':' . $port;
|
||||
}
|
||||
|
||||
if (isset($options['https'])) {
|
||||
if ($options['https'] === TRUE) {
|
||||
$options['base_url'] = str_replace('http://', 'https://', $options['base_url']);
|
||||
}
|
||||
elseif ($options['https'] === FALSE) {
|
||||
$options['base_url'] = str_replace('https://', 'http://', $options['base_url']);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Drupal's subfolder from the base_path if there is one.
|
||||
$options['base_url'] .= rtrim(base_path(), '/');
|
||||
if ($bubbleable_metadata) {
|
||||
$bubbleable_metadata->addCacheContexts(['languages:' . LanguageInterface::TYPE_URL, 'url.site']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLanguageSwitchLinks(Request $request, $type, Url $url) {
|
||||
$links = [];
|
||||
$query = [];
|
||||
parse_str($request->getQueryString() ?? '', $query);
|
||||
|
||||
foreach ($this->languageManager->getNativeLanguages() as $language) {
|
||||
$links[$language->getId()] = [
|
||||
// We need to clone the $url object to avoid using the same one for all
|
||||
// links. When the links are rendered, options are set on the $url
|
||||
// object, so if we use the same one, they would be set for all links.
|
||||
'url' => clone $url,
|
||||
'title' => $language->getName(),
|
||||
'language' => $language,
|
||||
'attributes' => ['class' => ['language-link']],
|
||||
'query' => $query,
|
||||
];
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\LanguageNegotiation;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\language\Attribute\LanguageNegotiation;
|
||||
use Drupal\language\LanguageNegotiationMethodBase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Determines the language to be assigned to URLs when none is detected.
|
||||
*
|
||||
* The language negotiation process has a fallback chain that ends with the
|
||||
* default language negotiation method. Each built-in language type has a
|
||||
* separate initialization:
|
||||
* - Interface language, which is the only configurable one, always gets a valid
|
||||
* value. If no request-specific language is detected, the default language
|
||||
* will be used.
|
||||
* - Content language merely inherits the interface language by default.
|
||||
* - URL language is detected from the requested URL and will be used to rewrite
|
||||
* URLs appearing in the page being rendered. If no language can be detected,
|
||||
* there are two possibilities:
|
||||
* - If the default language has no configured path prefix or domain, then the
|
||||
* default language is used. This guarantees that (missing) URL prefixes are
|
||||
* preserved when navigating through the site.
|
||||
* - If the default language has a configured path prefix or domain, a
|
||||
* requested URL having an empty prefix or domain is an anomaly that must be
|
||||
* fixed. This is done by introducing a prefix or domain in the rendered
|
||||
* page matching the detected interface language.
|
||||
*/
|
||||
#[LanguageNegotiation(
|
||||
id: LanguageNegotiationUrlFallback::METHOD_ID,
|
||||
name: new TranslatableMarkup('URL fallback'),
|
||||
types: [LanguageInterface::TYPE_URL],
|
||||
weight: 8,
|
||||
description: new TranslatableMarkup('Use an already detected language for URLs if none is found.'),
|
||||
)]
|
||||
class LanguageNegotiationUrlFallback extends LanguageNegotiationMethodBase {
|
||||
|
||||
/**
|
||||
* The language negotiation method id.
|
||||
*/
|
||||
const METHOD_ID = 'language-url-fallback';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode(?Request $request = NULL) {
|
||||
$langcode = NULL;
|
||||
|
||||
if ($this->languageManager) {
|
||||
$default = $this->languageManager->getDefaultLanguage();
|
||||
$config = $this->config->get('language.negotiation')->get('url');
|
||||
$prefix = ($config['source'] == LanguageNegotiationUrl::CONFIG_PATH_PREFIX);
|
||||
|
||||
// If the default language is not configured to convey language
|
||||
// information, a missing URL language information indicates that URL
|
||||
// language should be the default one, otherwise we fall back to an
|
||||
// already detected language.
|
||||
if (($prefix && empty($config['prefixes'][$default->getId()])) || (!$prefix && empty($config['domains'][$default->getId()]))) {
|
||||
$langcode = $default->getId();
|
||||
}
|
||||
else {
|
||||
$langcode = $this->languageManager->getCurrentLanguage()->getId();
|
||||
}
|
||||
}
|
||||
|
||||
return $langcode;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\destination;
|
||||
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\migrate\Attribute\MigrateDestination;
|
||||
use Drupal\migrate\MigrateException;
|
||||
use Drupal\migrate\Plugin\migrate\destination\Config;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Provides a destination plugin for the default langcode config.
|
||||
*/
|
||||
#[MigrateDestination('default_langcode')]
|
||||
class DefaultLangcode extends Config {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function import(Row $row, array $old_destination_id_values = []) {
|
||||
$destination = $row->getDestination();
|
||||
$langcode = $destination['default_langcode'];
|
||||
|
||||
// Check if the language exists.
|
||||
if (ConfigurableLanguage::load($langcode) === NULL) {
|
||||
throw new MigrateException("The language '$langcode' does not exist on this site.");
|
||||
}
|
||||
|
||||
$this->config->set('default_langcode', $destination['default_langcode']);
|
||||
$this->config->save();
|
||||
return [$this->config->getName()];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\Attribute\MigrateProcess;
|
||||
use Drupal\migrate\MigrateException;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Determines the content translation setting.
|
||||
*
|
||||
* The source value is an indexed array of three values:
|
||||
* - The language content type, e.g. '1'
|
||||
* - The entity_translation_entity_types, an array of entity types.
|
||||
* - An entity type used with entity translation, e.g. comment.
|
||||
*/
|
||||
#[MigrateProcess('content_translation_enabled_setting')]
|
||||
class ContentTranslationEnabledSetting extends ProcessPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
if (!is_array($value)) {
|
||||
throw new MigrateException('Input should be an array');
|
||||
}
|
||||
|
||||
[$language_content_type, $entity_translation_entity_types, $entity_type] = $value;
|
||||
|
||||
switch ($language_content_type) {
|
||||
// In the case of being 0, it will be skipped. We are not actually setting
|
||||
// a null value.
|
||||
case 0:
|
||||
$setting = NULL;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
$setting = FALSE;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$setting = FALSE;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// If entity translation is enabled return the status of comment
|
||||
// translations.
|
||||
$setting = FALSE;
|
||||
if (!empty($entity_translation_entity_types[$entity_type])) {
|
||||
$setting = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$setting = NULL;
|
||||
break;
|
||||
}
|
||||
return $setting;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\Attribute\MigrateProcess;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\Plugin\migrate\process\ArrayBuild;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* This plugin makes sure that no domain is empty if domain negotiation is used.
|
||||
*/
|
||||
#[MigrateProcess(
|
||||
id: "language_domains",
|
||||
handle_multiples: TRUE,
|
||||
)]
|
||||
class LanguageDomains extends ArrayBuild {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
if ($row->getSourceProperty('domain_negotiation_used')) {
|
||||
global $base_url;
|
||||
|
||||
foreach ($value as $old_key => $old_value) {
|
||||
if (empty($old_value['domain'])) {
|
||||
// The default language domain might be empty.
|
||||
// If it is, use the current domain.
|
||||
$value[$old_key]['domain'] = parse_url($base_url, PHP_URL_HOST);
|
||||
}
|
||||
else {
|
||||
// Ensure we have a protocol when checking for the hostname.
|
||||
$domain = 'http://' . str_replace(['http://', 'https://'], '', $old_value['domain']);
|
||||
// Only keep the host part of the domain.
|
||||
$value[$old_key]['domain'] = parse_url($domain, PHP_URL_HOST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::transform($value, $migrate_executable, $row, $destination_property);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\Attribute\MigrateProcess;
|
||||
use Drupal\migrate\MigrateException;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Processes the arrays for the language types' negotiation methods and weights.
|
||||
*/
|
||||
#[MigrateProcess(
|
||||
id: "language_negotiation",
|
||||
handle_multiples: TRUE,
|
||||
)]
|
||||
class LanguageNegotiation extends ProcessPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
$new_value = [
|
||||
'enabled' => [],
|
||||
'method_weights' => [],
|
||||
];
|
||||
|
||||
if (!is_array($value)) {
|
||||
throw new MigrateException('The input should be an array');
|
||||
}
|
||||
|
||||
// If no weights are provided, use the keys by flipping the array.
|
||||
if (empty($value[1])) {
|
||||
$new_value['enabled'] = array_flip(array_map([$this, 'mapNewMethods'], array_keys($value[0])));
|
||||
unset($new_value['method_weights']);
|
||||
}
|
||||
else {
|
||||
foreach ($value[1] as $method => $weight) {
|
||||
$new_method = $this->mapNewMethods($method);
|
||||
$new_value['method_weights'][$new_method] = $weight;
|
||||
if (in_array($method, array_keys($value[0]))) {
|
||||
$new_value['enabled'][$new_method] = $weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps old negotiation method names to the new ones.
|
||||
*
|
||||
* @param string $value
|
||||
* The old negotiation method name.
|
||||
*
|
||||
* @return string
|
||||
* The new negotiation method name.
|
||||
*/
|
||||
protected function mapNewMethods($value) {
|
||||
switch ($value) {
|
||||
case 'language-default':
|
||||
return 'language-selected';
|
||||
|
||||
case 'locale-browser':
|
||||
return 'language-browser';
|
||||
|
||||
case 'locale-interface':
|
||||
return 'language-interface';
|
||||
|
||||
case 'locale-session':
|
||||
return 'language-session';
|
||||
|
||||
case 'locale-url':
|
||||
return 'language-url';
|
||||
|
||||
case 'locale-url-fallback':
|
||||
return 'language-url-fallback';
|
||||
|
||||
case 'locale-user':
|
||||
return 'language-user';
|
||||
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\process;
|
||||
|
||||
use Drupal\migrate\Attribute\MigrateProcess;
|
||||
use Drupal\migrate\MigrateException;
|
||||
use Drupal\migrate\MigrateExecutableInterface;
|
||||
use Drupal\migrate\ProcessPluginBase;
|
||||
use Drupal\migrate\Row;
|
||||
|
||||
/**
|
||||
* Processes the array for the language types.
|
||||
*/
|
||||
#[MigrateProcess(
|
||||
id: "language_types",
|
||||
handle_multiples: TRUE,
|
||||
)]
|
||||
class LanguageTypes extends ProcessPluginBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
|
||||
if (!is_array($value)) {
|
||||
throw new MigrateException('The input should be an array');
|
||||
}
|
||||
|
||||
if (array_key_exists('language', $value)) {
|
||||
$value['language_interface'] = $value['language'];
|
||||
unset($value['language']);
|
||||
}
|
||||
|
||||
if (!empty($this->configuration['filter_configurable'])) {
|
||||
$value = array_filter($value);
|
||||
}
|
||||
|
||||
return array_keys($value);
|
||||
}
|
||||
|
||||
}
|
||||
103
web/core/modules/language/src/Plugin/migrate/source/Language.php
Normal file
103
web/core/modules/language/src/Plugin/migrate/source/Language.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\source;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 6/7 language source from database.
|
||||
*
|
||||
* Available configuration keys:
|
||||
* - fetch_all: (optional) If not empty, all source languages are retrieved and
|
||||
* available as "languages" source property. Each language is an array with
|
||||
* the same structure as a source row.
|
||||
* - domain_negotiation: (optional) If not empty and domain negotiation is
|
||||
* enabled in the source database, the "domain_negotiation_used" source
|
||||
* property is set to TRUE.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* @code
|
||||
* plugin: language
|
||||
* fetch_all: true
|
||||
* domain_negotiation: true
|
||||
* @endcode
|
||||
*
|
||||
* In this example, available languages are retrieved from the source database.
|
||||
* Given that fetch_all and domain_negotiation are specified, each row also
|
||||
* contains all languages and the domain negotiation status, if enabled.
|
||||
*
|
||||
* For additional configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBase
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "language",
|
||||
* source_module = "locale"
|
||||
* )
|
||||
*/
|
||||
class Language extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'language' => $this->t('The language code.'),
|
||||
'name' => $this->t('The English name of the language.'),
|
||||
'native' => $this->t('The native name of the language.'),
|
||||
'direction' => $this->t('The language direction. (0 = LTR, 1 = RTL)'),
|
||||
'enabled' => $this->t('Whether the language is enabled.'),
|
||||
'plurals' => $this->t('Number of plural indexes in this language.'),
|
||||
'formula' => $this->t('PHP formula to get plural indexes.'),
|
||||
'domain' => $this->t('Domain to use for this language.'),
|
||||
'prefix' => $this->t('Path prefix used for this language.'),
|
||||
'weight' => $this->t('The language weight when listed.'),
|
||||
'javascript' => $this->t('Location of the JavaScript translation file.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
return [
|
||||
'language' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('languages')->fields('languages');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
if (!empty($this->configuration['fetch_all'])) {
|
||||
// Get an array of all languages.
|
||||
$languages = $this->query()->execute()->fetchAll();
|
||||
$row->setSourceProperty('languages', $languages);
|
||||
}
|
||||
|
||||
if (!empty($this->configuration['domain_negotiation'])) {
|
||||
// Check if domain negotiation is used to be able to fill in the default
|
||||
// language domain, which may be empty. In D6, domain negotiation is used
|
||||
// when the 'language_negotiation' variable is set to '3', and in D7, when
|
||||
// the 'locale_language_negotiation_url_part' variable is set to '1'.
|
||||
if ($this->variableGet('language_negotiation', 0) == 3 || $this->variableGet('locale_language_negotiation_url_part', 0) == 1) {
|
||||
$row->setSourceProperty('domain_negotiation_used', TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 6 i18n node settings from database.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBas
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_language_content_settings",
|
||||
* source_module = "locale"
|
||||
* )
|
||||
*/
|
||||
class LanguageContentSettings extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('node_type', 't')
|
||||
->fields('t', [
|
||||
'type',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
$fields = [
|
||||
'type' => $this->t('Type'),
|
||||
'language_content_type' => $this->t('Multilingual support.'),
|
||||
'i18n_lock_node' => $this->t('Lock language.'),
|
||||
];
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$type = $row->getSourceProperty('type');
|
||||
$row->setSourceProperty('language_content_type', $this->variableGet('language_content_type_' . $type, NULL));
|
||||
$row->setSourceProperty('i18n_lock_node', $this->variableGet('i18n_lock_node_' . $type, 0));
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['type']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\source\d6;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
// cspell:ignore localizable
|
||||
|
||||
/**
|
||||
* Drupal 6 i18n vocabularies source from database.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBas
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d6_language_content_settings_taxonomy_vocabulary",
|
||||
* source_module = "taxonomy"
|
||||
* )
|
||||
*/
|
||||
class LanguageContentSettingsTaxonomyVocabulary extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = $this->select('vocabulary', 'v')
|
||||
->fields('v', ['vid']);
|
||||
if ($this->getDatabase()
|
||||
->schema()
|
||||
->fieldExists('vocabulary', 'language')) {
|
||||
$query->addField('v', 'language');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
return [
|
||||
'vid' => $this->t('The vocabulary ID.'),
|
||||
'language' => $this->t('The default language for new terms.'),
|
||||
'state' => $this->t('The i18n taxonomy translation setting.'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
// Get the i18n taxonomy translation setting for this vocabulary.
|
||||
// 0 - No multilingual options
|
||||
// 1 - Localizable terms. Run through the localization system.
|
||||
// 2 - Predefined language for a vocabulary and its terms.
|
||||
// 3 - Per-language terms, translatable (referencing terms with different
|
||||
// languages) but not localizable.
|
||||
$i18ntaxonomy_vocabulary = $this->variableGet('i18ntaxonomy_vocabulary', []);
|
||||
$vid = $row->getSourceProperty('vid');
|
||||
$state = 0;
|
||||
if (array_key_exists($vid, $i18ntaxonomy_vocabulary)) {
|
||||
$state = $i18ntaxonomy_vocabulary[$vid];
|
||||
}
|
||||
$row->setSourceProperty('state', $state);
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['vid']['type'] = 'integer';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\migrate\Row;
|
||||
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
|
||||
|
||||
/**
|
||||
* Drupal 7 i18n node settings from database.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBas
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_language_content_settings",
|
||||
* source_module = "locale"
|
||||
* )
|
||||
*/
|
||||
class LanguageContentSettings extends DrupalSqlBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
return $this->select('node_type', 't')
|
||||
->fields('t', [
|
||||
'type',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
$fields = [
|
||||
'type' => $this->t('Type'),
|
||||
'language_content_type' => $this->t('Multilingual support.'),
|
||||
'i18n_lock_node' => $this->t('Lock language.'),
|
||||
];
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareRow(Row $row) {
|
||||
$type = $row->getSourceProperty('type');
|
||||
$row->setSourceProperty('language_content_type', $this->variableGet('language_content_type_' . $type, NULL));
|
||||
$i18n_node_options = $this->variableGet('i18n_node_options_' . $type, NULL);
|
||||
if ($i18n_node_options && in_array('lock', $i18n_node_options)) {
|
||||
$row->setSourceProperty('i18n_lock_node', 1);
|
||||
}
|
||||
else {
|
||||
$row->setSourceProperty('i18n_lock_node', 0);
|
||||
}
|
||||
|
||||
// Get the entity translation entity settings.
|
||||
$entity_translation_entity_types = $this->variableGet('entity_translation_entity_types', NULL);
|
||||
$row->setSourceProperty('entity_translation_entity_types', $entity_translation_entity_types);
|
||||
return parent::prepareRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIds() {
|
||||
$ids['type']['type'] = 'string';
|
||||
return $ids;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\language\Plugin\migrate\source\d7;
|
||||
|
||||
use Drupal\taxonomy\Plugin\migrate\source\d7\Vocabulary;
|
||||
|
||||
/**
|
||||
* Drupal 7 i18n vocabularies source from database.
|
||||
*
|
||||
* For available configuration keys, refer to the parent classes.
|
||||
*
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SqlBase
|
||||
* @see \Drupal\migrate\Plugin\migrate\source\SourcePluginBas
|
||||
*
|
||||
* @MigrateSource(
|
||||
* id = "d7_language_content_settings_taxonomy_vocabulary",
|
||||
* source_module = "i18n_taxonomy"
|
||||
* )
|
||||
*/
|
||||
class LanguageContentSettingsTaxonomyVocabulary extends Vocabulary {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query() {
|
||||
$query = parent::query();
|
||||
if ($this->getDatabase()
|
||||
->schema()
|
||||
->fieldExists('taxonomy_vocabulary', 'i18n_mode')) {
|
||||
$query->addField('v', 'language');
|
||||
$query->addField('v', 'i18n_mode');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fields() {
|
||||
$fields = parent::fields();
|
||||
$fields['language'] = $this->t('i18n language');
|
||||
$fields['i18n_mode'] = $this->t('i18n mode');
|
||||
return $fields;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user