diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php index 0072f0c..4f242c2 100644 --- a/core/lib/Drupal/Core/Language/LanguageManager.php +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -75,7 +75,28 @@ public function isMultilingual() { * {@inheritdoc} */ public function getLanguageTypes() { - return array(LanguageInterface::TYPE_INTERFACE, LanguageInterface::TYPE_CONTENT, LanguageInterface::TYPE_URL); + return array_keys($this->getDefinedLanguageTypesInfo()); + } + + /** + * {@inheritdoc} + */ + public function getDefinedLanguageTypesInfo() { + return array( + LanguageInterface::TYPE_INTERFACE => array( + 'name' => t('User interface text'), + 'description' => t('Order of language detection methods for user interface text. If a translation of user interface text is available in the detected language, it will be displayed.'), + 'locked' => TRUE, + ), + LanguageInterface::TYPE_CONTENT => array( + 'name' => t('Content'), + 'description' => t('Order of language detection methods for content. If a version of content is available in the detected language, it will be displayed.'), + 'locked' => TRUE, + ), + LanguageInterface::TYPE_URL => array( + 'locked' => TRUE, + ), + ); } /** diff --git a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php index b3f0272..49d0421 100644 --- a/core/lib/Drupal/Core/Language/LanguageManagerInterface.php +++ b/core/lib/Drupal/Core/Language/LanguageManagerInterface.php @@ -39,6 +39,17 @@ public function isMultilingual(); public function getLanguageTypes(); /** + * Returns information about all defined language types. + * + * @see hook_language_types_info() + * + * @return array + * An associative array of language type information arrays keyed by type + * names. Similar to hook_language_types_info(). + */ + public function getDefinedLanguageTypesInfo(); + + /** * Returns the current language for the given type. * * @param string $type diff --git a/core/modules/comment/config/install/views.view.comments_recent.yml b/core/modules/comment/config/install/views.view.comments_recent.yml index 674c8a8..7efdf8f 100644 --- a/core/modules/comment/config/install/views.view.comments_recent.yml +++ b/core/modules/comment/config/install/views.view.comments_recent.yml @@ -229,7 +229,7 @@ display: content: 'No comments available.' tokenize: false plugin_id: text_custom - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null block_1: provider: block @@ -240,7 +240,7 @@ display: display_options: block_description: 'Recent comments' block_category: 'Lists (Views)' - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null allow: items_per_page: true diff --git a/core/modules/field/src/Plugin/views/field/Field.php b/core/modules/field/src/Plugin/views/field/Field.php index 4705437..ed17cc1 100644 --- a/core/modules/field/src/Plugin/views/field/Field.php +++ b/core/modules/field/src/Plugin/views/field/Field.php @@ -298,12 +298,11 @@ public function query($use_groupby = FALSE) { // LanguageInterface::LANGCODE_NOT_SPECIFIED in reality so allow it as // well. // @see this::field_langcode() - $default_langcode = language_default()->id; - $langcode = str_replace( - array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'), - array($this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT), $default_langcode), - $this->view->display_handler->options['field_langcode'] - ); + $langcode = $this->view->display_handler->options['field_langcode']; + $substitutions = views_language_type_substitutions_options('id', 'value'); + if (isset($substitutions[$langcode])) { + $langcode = $substitutions[$langcode]; + } $placeholder = $this->placeholder(); $langcode_fallback_candidates = $this->languageManager->getFallbackCandidates($langcode, array('operation' => 'views_query', 'data' => $this)); $this->query->addWhereExpression(0, "$column IN($placeholder) OR $column IS NULL", array($placeholder => $langcode_fallback_candidates)); @@ -915,12 +914,11 @@ protected function addSelfTokens(&$tokens, $item) { */ function field_langcode(EntityInterface $entity) { if ($this->getFieldDefinition()->isTranslatable()) { - $default_langcode = language_default()->id; - $langcode = str_replace( - array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'), - array($this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id, $default_langcode), - $this->view->display_handler->options['field_langcode'] - ); + $langcode = $this->view->display_handler->options['field_langcode']; + $substitutions = views_language_type_substitutions_options('id', 'value'); + if (isset($substitutions[$langcode])) { + $langcode = $substitutions[$langcode]; + } // Give the Entity Field API a chance to fallback to a different language // (or LanguageInterface::LANGCODE_NOT_SPECIFIED), in case the field has diff --git a/core/modules/node/config/install/views.view.content.yml b/core/modules/node/config/install/views.view.content.yml index 132ffee..6229a32 100644 --- a/core/modules/node/config/install/views.view.content.yml +++ b/core/modules/node/config/install/views.view.content.yml @@ -536,7 +536,7 @@ display: operator: AND groups: 1: AND - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null display_plugin: default display_title: Master @@ -558,7 +558,7 @@ display: description: 'Find and manage content' menu_name: admin weight: -10 - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null display_plugin: page display_title: Page diff --git a/core/modules/node/config/install/views.view.frontpage.yml b/core/modules/node/config/install/views.view.frontpage.yml index 1e27e9c..af7cd23 100644 --- a/core/modules/node/config/install/views.view.frontpage.yml +++ b/core/modules/node/config/install/views.view.frontpage.yml @@ -130,7 +130,7 @@ display: - views operator: in value: - '***CURRENT_LANGUAGE***': '***CURRENT_LANGUAGE***' + language_content: 'language_content' group: 1 exposed: false expose: @@ -240,7 +240,7 @@ display: relationships: { } fields: { } arguments: { } - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null display_plugin: default display_title: Master @@ -249,7 +249,7 @@ display: page_1: display_options: path: node - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null display_plugin: page display_title: Page @@ -286,5 +286,5 @@ display: view_mode: rss links: false provider: views - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null diff --git a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml index 68fb2d5..8ecac76 100644 --- a/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml @@ -300,7 +300,7 @@ display: validate_options: { } plugin_id: language provider: views - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null page_1: display_plugin: page @@ -309,6 +309,6 @@ display: position: 1 provider: views display_options: - field_langcode: '***CURRENT_LANGUAGE***' + field_langcode: 'language_content' field_langcode_add_to_query: null path: test-language diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 31f30bc..e8a6550 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -579,7 +579,7 @@ protected function defineOptions() { 'bool' => TRUE, ), 'field_langcode' => array( - 'default' => '***CURRENT_LANGUAGE***', + 'default' => LanguageInterface::TYPE_CONTENT, ), 'field_langcode_add_to_query' => array( 'default' => TRUE, @@ -1245,18 +1245,14 @@ public function optionsSummary(&$categories, &$options) { 'desc' => t('Allow to set some advanced settings for the query plugin'), ); - $languages = array( - '***CURRENT_LANGUAGE***' => t("Current user's language"), - '***DEFAULT_LANGUAGE***' => t("Default site language"), - LanguageInterface::LANGCODE_NOT_SPECIFIED => t('Language neutral'), + $language_options = array_merge( + views_language_type_substitutions_options('id', 'label'), + views_language_list() ); - if (\Drupal::moduleHandler()->moduleExists('language')) { - $languages = array_merge($languages, language_list()); - } $options['field_langcode'] = array( 'category' => 'other', 'title' => t('Field Language'), - 'value' => $languages[$this->getOption('field_langcode')], + 'value' => $language_options[$this->getOption('field_langcode')], 'desc' => t('All fields which support translations will be displayed in the selected language.'), ); @@ -1619,18 +1615,14 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { // an entity base table. Also, we make sure that there's at least one // entity type with a translation handler attached. if (in_array($this->view->storage->get('base_table'), $translatable_entity_tables)) { - $languages = array( - '***CURRENT_LANGUAGE***' => t("Current user's language"), - '***DEFAULT_LANGUAGE***' => t("Default site language"), - LanguageInterface::LANGCODE_NOT_SPECIFIED => t('Language neutral'), - ); - $languages = array_merge($languages, views_language_list()); - $form['field_langcode'] = array( '#type' => 'select', '#title' => t('Field Language'), '#description' => t('All fields which support translations will be displayed in the selected language.'), - '#options' => $languages, + '#options' => array_merge( + views_language_type_substitutions_options('id', 'label'), + views_language_list() + ), '#default_value' => $this->getOption('field_langcode'), ); $form['field_langcode_add_to_query'] = array( diff --git a/core/modules/views/src/Plugin/views/filter/LanguageFilter.php b/core/modules/views/src/Plugin/views/filter/LanguageFilter.php index 8b08f33..5a3f022 100644 --- a/core/modules/views/src/Plugin/views/filter/LanguageFilter.php +++ b/core/modules/views/src/Plugin/views/filter/LanguageFilter.php @@ -16,16 +16,59 @@ */ class LanguageFilter extends InOperator { + /** + * {@inheritdoc} + */ public function getValueOptions() { if (!isset($this->value_options)) { $this->value_title = t('Language'); - $languages = array( - '***CURRENT_LANGUAGE***' => t("Current user's language"), - '***DEFAULT_LANGUAGE***' => t("Default site language"), + $this->value_options = array_merge( + views_language_type_substitutions_options('id', 'label'), + views_language_list() ); - $languages = array_merge($languages, views_language_list()); - $this->value_options = $languages; } } + /** + * {@inheritdoc} + */ + protected function opSimple() { + if (empty($this->value)) { + return; + } + $this->ensureMyTable(); + + // We use array_values() because the checkboxes keep keys and that can cause + // array addition problems. + $value = $this->resolveValue(); + $this->query->addWhere($this->options['group'], "$this->tableAlias.$this->realField", array_values($value), $this->operator); + } + + /** + * Convert the machine name of a language type to substitution. + * + * @return null|string + * If the value is not a language type then returns it without any + * modification. The language types are converted to views substitutions. + */ + protected function resolveValue() { + $value = $this->value; + + $substitutions = views_language_type_substitutions_options('id', 'placeholder'); + if (is_array($value)) { + foreach ($value as $key => $language_type) { + if (isset($substitutions[$language_type])) { + $value[$key] = $substitutions[$language_type]; + } + } + } + else { + if (isset($substitutions[$value])) { + $value = $substitutions[$value]; + } + } + + return $value; + } + } diff --git a/core/modules/views/views.api.php b/core/modules/views/views.api.php index e5c8c50..5194ed6 100644 --- a/core/modules/views/views.api.php +++ b/core/modules/views/views.api.php @@ -569,8 +569,8 @@ function hook_views_query_substitutions(ViewExecutable $view) { return array( '***CURRENT_VERSION***' => \Drupal::VERSION, '***CURRENT_TIME***' => REQUEST_TIME, - '***CURRENT_LANGUAGE***' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id, - '***DEFAULT_LANGUAGE***' => \Drupal::languageManager()->getDefaultLanguage()->id, + '***LANGUAGE_CONTENT***' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id, + '***LANGUAGE_DEFAULT***' => \Drupal::languageManager()->getDefaultLanguage()->id, ); } diff --git a/core/modules/views/views.module b/core/modules/views/views.module index 3294836..d34e675 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -509,6 +509,65 @@ function views_language_list($field = 'name', $flags = LanguageInterface::STATE_ } /** + * @return array + * - id: @todo + * - placeholder: @todo + * - value: @todo + * - label: @todo + */ +function views_language_type_substitutions() { + static $substitutions = NULL; + + if ($substitutions === NULL) { + $substitutions = array( + // @todo The problem is that this key is not prefixed with "language_". + LanguageInterface::LANGCODE_DEFAULT => array( + 'id' => LanguageInterface::LANGCODE_DEFAULT, + 'placeholder' => '***LANGUAGE_DEFAULT***', + 'value' => language_default()->getId(), + 'label' => t('Default site language'), + ), + ); + + $language_manager = \Drupal::languageManager(); + foreach ($language_manager->getDefinedLanguageTypesInfo() as $language_type_id => $language_type) { + $language = $language_manager->getCurrentLanguage($language_type_id); + $substitutions[$language_type_id] = array( + 'id' => $language_type_id, + 'placeholder' => '***' . drupal_strtoupper($language_type_id) . '***', + 'value' => $language->getId(), + 'label' => '', + ); + + if (!empty($language_type['name'])) { + $substitutions[$language_type_id]['label'] = t('Language negotiated for @name', array( + '@name' => $language_type['name'], + )); + } + } + } + + return $substitutions; +} + +/** + * @param string $key + * @param string $value + * + * @return array + */ +function views_language_type_substitutions_options($key, $value) { + $substitutions = array(); + foreach (views_language_type_substitutions() as $substitution) { + if ($key != 'label' && $value != 'label' || !empty($substitution['label'])) { + $substitutions[$substitution[$key]] = $substitution[$value]; + } + } + + return $substitutions; +} + +/** * Implements hook_ENTITY_TYPE_create() for 'field_instance_config'. */ function views_field_instance_config_create(FieldInstanceConfigInterface $field_instance) { diff --git a/core/modules/views/views.views_execution.inc b/core/modules/views/views.views_execution.inc index 96b5006..83b5d10 100644 --- a/core/modules/views/views.views_execution.inc +++ b/core/modules/views/views.views_execution.inc @@ -14,10 +14,10 @@ * Substitute current time; this works with cached queries. */ function views_views_query_substitutions(ViewExecutable $view) { - return array( + $substitutions = array( '***CURRENT_VERSION***' => \Drupal::VERSION, '***CURRENT_TIME***' => REQUEST_TIME, - '***CURRENT_LANGUAGE***' => \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->id, - '***DEFAULT_LANGUAGE***' => \Drupal::languageManager()->getDefaultLanguage()->id, - ); + ) + views_language_type_substitutions_options('placeholder', 'value'); + + return $substitutions; } diff --git a/core/modules/views_ui/src/Tests/ViewEditTest.php b/core/modules/views_ui/src/Tests/ViewEditTest.php index b88ed43..a894f97 100644 --- a/core/modules/views_ui/src/Tests/ViewEditTest.php +++ b/core/modules/views_ui/src/Tests/ViewEditTest.php @@ -94,7 +94,7 @@ public function testEditFormOtherOptions() { $this->drupalGet('admin/structure/views/view/test_view'); $langcode_url = 'admin/structure/views/nojs/display/test_view/default/field_langcode'; $this->assertLinkByHref($langcode_url); - $this->assertLink(t("Current user's language")); + $this->assertLink(t('Language negotiated for @name', array('@name' => t('Content')))); // Click the link and check the form before language is added. $this->drupalGet($langcode_url); $this->assertResponse(200); @@ -106,7 +106,7 @@ public function testEditFormOtherOptions() { $this->drupalGet('admin/structure/views/nojs/display/test_display/page_1/field_langcode'); $this->assertResponse(200); - $this->assertFieldByName('field_langcode', '***CURRENT_LANGUAGE***'); + $this->assertFieldByName('field_langcode', 'language_content'); $this->assertFieldByName('field_langcode_add_to_query', TRUE); }