diff --git a/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php b/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php index 10664da..18e674c 100644 --- a/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php +++ b/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php @@ -182,6 +182,24 @@ function testSettingsUI() { $this->assertEqual($definitions['body']->isTranslatable(), $translatable, 'Field translatability correctly switched.'); $this->assertEqual($field->isTranslatable(), $definitions['body']->isTranslatable(), 'Configurable field translatability correctly switched.'); } + + // Test that the order of the language list is similar to other language + // lists, such as in Views UI. + $this->drupalGet('admin/config/regional/content-language'); + + $expected_elements = array( + 'site_default', + 'current_interface', + 'authors_default', + 'en', + 'und', + 'zxx', + ); + $elements = $this->xpath('//select[@id="edit-settings-node-article-settings-language-langcode"]/option'); + // Compare values inside the option elements with expected values. + for ($i = 0; $i < count($elements); $i++) { + $this->assertEqual($elements[$i]->attributes()->{'value'}, $expected_elements[$i]); + } } /** diff --git a/core/modules/language/src/Element/LanguageConfiguration.php b/core/modules/language/src/Element/LanguageConfiguration.php index aa6f94b..82c6f8f 100644 --- a/core/modules/language/src/Element/LanguageConfiguration.php +++ b/core/modules/language/src/Element/LanguageConfiguration.php @@ -97,7 +97,7 @@ public static function processLanguageConfiguration(&$element, FormStateInterfac protected static function getDefaultOptions() { $language_options = array( LanguageInterface::LANGCODE_SITE_DEFAULT => t("Site's default language (!language)", array('!language' => static::languageManager()->getDefaultLanguage()->getName())), - 'current_interface' => t('Current interface language'), + 'current_interface' => t('!type language selected for page', array('!type' => t('User interface text'))), 'authors_default' => t("Author's preferred language"), ); diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php index 9c0f49b..658050d 100644 --- a/core/modules/views/src/Plugin/views/PluginBase.php +++ b/core/modules/views/src/Plugin/views/PluginBase.php @@ -507,14 +507,17 @@ public function getProvider() { * - \Drupal\views\Plugin\views\PluginBase::INCLUDE_ENTITY: Add * entity row language types. Note that these are only supported for * display options, not substituted in queries. + * @param array|null $current_values + * The list of current values if available so we add them to the list. * * @return array * An array of language names, keyed by the language code. Negotiated and * special languages have special codes that are substituted in queries by * PluginBase::queryLanguageSubstitutions(). */ - protected function listLanguages($flags = LanguageInterface::STATE_ALL) { + protected function listLanguages($flags = LanguageInterface::STATE_ALL, array $current_values = NULL) { $manager = \Drupal::languageManager(); + $languages = $manager->getLanguages($flags); $list = array(); // The entity languages should come first, if requested. @@ -523,32 +526,47 @@ protected function listLanguages($flags = LanguageInterface::STATE_ALL) { $list['***LANGUAGE_entity_default***'] = $this->t('Original language of content in view row'); } - // The Language Manager class takes care of the STATE_SITE_DEFAULT case. - // It comes in with ID set to LanguageInterface::LANGCODE_SITE_DEFAULT. + // STATE_SITE_DEFAULT comes in with ID set to LanguageInterface::LANGCODE_SITE_DEFAULT. // Since this is not a real language, surround it by '***LANGUAGE_...***', // like the negotiated languages below. - $languages = $manager->getLanguages($flags); - foreach ($languages as $id => $language) { - if ($id == LanguageInterface::LANGCODE_SITE_DEFAULT) { - $id = PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT; - } - $list[$id] = $this->t($language->getName()); + if ($flags & LanguageInterface::STATE_SITE_DEFAULT) { + $list[PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT] = $this->t($languages[LanguageInterface::LANGCODE_SITE_DEFAULT]->getName()); + // Remove site default language from $languages so it's not added + // with the real languages below. + unset($languages[LanguageInterface::LANGCODE_SITE_DEFAULT]); } // Add in negotiated languages, if requested. if ($flags & PluginBase::INCLUDE_NEGOTIATED) { - $types = $manager->getDefinedLanguageTypesInfo(); - foreach ($types as $id => $type) { - // Omit unnamed types. These are things like language_url, which are - // not configurable and do not need to be in this list. And surround - // IDs by '***LANGUAGE_...***', to avoid query collisions. - if (isset($type['name'])) { + $types_info = $manager->getDefinedLanguageTypesInfo(); + $types = $manager->getLanguageTypes(); + // We only go through the configured types. + foreach ($types as $id) { + if (isset($types_info[$id]['name'])) { + $name = $types_info[$id]['name']; + // Surround IDs by '***LANGUAGE_...***', to avoid query collisions. + $id = '***LANGUAGE_' . $id . '***'; + $list[$id] = $this->t('!type language selected for page', array('!type' => $name)); + } + } + if (!empty($current_values)) { + foreach ($types_info as $id => $type) { $id = '***LANGUAGE_' . $id . '***'; - $list[$id] = $this->t('!type language selected for page', array('!type' => $type['name'])); + // If this (non-configurable) type is among the current values, + // add that option too, so it is not lost. If not among the current + // values, skip displaying it to avoid user confusion. + if (isset($type['name']) && !isset($list[$id]) && in_array($id, $current_values)) { + $list[$id] = $this->t('!type language selected for page', array('!type' => $type['name'])); + } } } } + // Add real languages. + foreach ($languages as $id => $language) { + $list[$id] = $this->t($language->getName()); + } + return $list; } diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index 290d1a7..621e6c5 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -2609,7 +2609,9 @@ public function getExtenders() { */ protected function buildRenderingLanguageOptions() { // @todo Consider making these plugins. See https://drupal.org/node/2173811. - return $this->listLanguages(LanguageInterface::STATE_CONFIGURABLE | LanguageInterface::STATE_SITE_DEFAULT | PluginBase::INCLUDE_NEGOTIATED | PluginBase::INCLUDE_ENTITY); + // Pass the current rendering language (in this case a one element array) so + // is not lost when there is language configuration changes. + return $this->listLanguages(LanguageInterface::STATE_CONFIGURABLE | LanguageInterface::STATE_SITE_DEFAULT | PluginBase::INCLUDE_NEGOTIATED | PluginBase::INCLUDE_ENTITY, array($this->getOption('rendering_language'))); } /** diff --git a/core/modules/views/src/Plugin/views/filter/LanguageFilter.php b/core/modules/views/src/Plugin/views/filter/LanguageFilter.php index 9826998..acf59e7 100644 --- a/core/modules/views/src/Plugin/views/filter/LanguageFilter.php +++ b/core/modules/views/src/Plugin/views/filter/LanguageFilter.php @@ -65,7 +65,9 @@ public static function create(ContainerInterface $container, array $configuratio public function getValueOptions() { if (!isset($this->valueOptions)) { $this->valueTitle = $this->t('Language'); - $this->valueOptions = $this->listLanguages(LanguageInterface::STATE_ALL |LanguageInterface::STATE_SITE_DEFAULT | PluginBase::INCLUDE_NEGOTIATED); + // Pass the current values so options that are already selected do not get + // lost when there is changes in the language configuration. + $this->valueOptions = $this->listLanguages(LanguageInterface::STATE_ALL | LanguageInterface::STATE_SITE_DEFAULT | PluginBase::INCLUDE_NEGOTIATED, array_keys($this->value)); } } diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml index 7b8490a..9a0b910 100644 --- a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_display.yml @@ -39,6 +39,46 @@ display: plugin_id: boolean entity_type: node entity_field: status + langcode: + id: langcode + table: node_field_data + field: langcode + relationship: none + group_type: group + admin_label: '' + operator: in + value: + '***LANGUAGE_language_content***': '***LANGUAGE_language_content***' + group: 1 + exposed: false + expose: + operator_id: '' + label: '' + description: '' + use_operator: false + operator: '' + identifier: '' + required: false + remember: false + multiple: false + remember_roles: + authenticated: authenticated + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: language + entity_type: node + entity_field: langcode pager: options: items_per_page: 10 diff --git a/core/modules/views_ui/src/Tests/UITestBase.php b/core/modules/views_ui/src/Tests/UITestBase.php index f8cef54..1fe0cec 100644 --- a/core/modules/views_ui/src/Tests/UITestBase.php +++ b/core/modules/views_ui/src/Tests/UITestBase.php @@ -35,6 +35,9 @@ */ public static $modules = array('node', 'views_ui', 'block', 'taxonomy'); + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); @@ -42,7 +45,13 @@ protected function setUp() { $this->adminUser = $this->drupalCreateUser(array('administer views')); - $this->fullAdminUser = $this->drupalCreateUser(array('administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view all revisions')); + $this->fullAdminUser = $this->drupalCreateUser(array('administer views', + 'administer blocks', + 'bypass node access', + 'access user profiles', + 'view all revisions', + 'administer permissions', + )); $this->drupalLogin($this->fullAdminUser); } diff --git a/core/modules/views_ui/src/Tests/ViewEditTest.php b/core/modules/views_ui/src/Tests/ViewEditTest.php index d9cd747..4d57245 100644 --- a/core/modules/views_ui/src/Tests/ViewEditTest.php +++ b/core/modules/views_ui/src/Tests/ViewEditTest.php @@ -110,7 +110,7 @@ public function testEditFormLanguageOptions() { } // Make the site multilingual and test the options again. - $this->container->get('module_installer')->install(array('language')); + $this->container->get('module_installer')->install(array('language', 'content_translation')); ConfigurableLanguage::createFromLangcode('hu')->save(); $this->resetAll(); $this->rebuildContainer(); @@ -138,6 +138,73 @@ public function testEditFormLanguageOptions() { } else { $this->assertFieldByName('rendering_language', '***LANGUAGE_entity_translation***'); + // Test that the order of the language list is similar to other language + // lists, such as in Views UI. + $expected_elements = array( + '***LANGUAGE_entity_translation***', + '***LANGUAGE_entity_default***', + '***LANGUAGE_site_default***', + '***LANGUAGE_language_interface***', + 'en', + 'hu', + ); + $elements = $this->xpath('//select[@id="edit-rendering-language"]/option'); + // Compare values inside the option elements with expected values. + for ($i = 0; $i < count($elements); $i++) { + $this->assertEqual($elements[$i]->attributes()->{'value'}, $expected_elements[$i]); + } + + // Check that the selected values are respected even we they are not + // suposed to be listed. + // Give permission to edit languages to authenticated users. + $edit = [ + 'authenticated[administer languages]' => TRUE, + ]; + $this->drupalPostForm('/admin/people/permissions', $edit, t('Save permissions')); + // Enable Content language negotiation so we have one more item + // to select. + $edit = [ + 'language_content[configurable]' => TRUE, + ]; + $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings')); + + // Choose the new negotiation as the rendering language. + $edit = [ + 'rendering_language' => '***LANGUAGE_language_content***', + ]; + $this->drupalPostForm('/admin/structure/views/nojs/display/' . $view_name . '/' . $display . '/rendering_language', $edit, t('Apply')); + + // Disable language content negotiation. + $edit = [ + 'language_content[configurable]' => FALSE, + ]; + $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings')); + + // Check that the previous selection is listed and selected. + $this->drupalGet($langcode_url); + $element = $this->xpath('//select[@id="edit-rendering-language"]/option[@value="***LANGUAGE_language_content***" and @selected="selected"]'); + $this->assertFalse(empty($element), 'Current selection is not lost'); + + // Check the order for the langcode filter. + $langcode_url = 'admin/structure/views/nojs/handler/' . $view_name . '/' . $display . '/filter/langcode'; + $this->drupalGet($langcode_url); + $this->assertResponse(200); + + $expected_elements = array( + 'all', + '***LANGUAGE_site_default***', + '***LANGUAGE_language_interface***', + '***LANGUAGE_language_content***', + 'en', + 'hu', + 'und', + 'zxx', + ); + $elements = $this->xpath('//div[@id="edit-options-value"]//input'); + // Compare values inside the option elements with expected values. + for ($i = 0; $i < count($elements); $i++) { + $this->assertEqual($elements[$i]->attributes()->{'value'}, $expected_elements[$i]); + } } } }