diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php index c180847..7560949 100644 --- a/core/lib/Drupal/Core/Language/LanguageManager.php +++ b/core/lib/Drupal/Core/Language/LanguageManager.php @@ -96,8 +96,8 @@ public function getDefinedLanguageTypesInfo() { // access names and descriptions of the default language types. return array( LanguageInterface::TYPE_INTERFACE => array( - 'name' => $this->t('User interface text'), - 'description' => $this->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.'), + 'name' => $this->t('Interface text'), + 'description' => $this->t('Order of language detection methods for interface text. If a translation of interface text is available in the detected language, it will be displayed.'), 'locked' => TRUE, ), LanguageInterface::TYPE_CONTENT => array( diff --git a/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php b/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php index 10664da..c979c5b 100644 --- a/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php +++ b/core/modules/content_translation/src/Tests/ContentTranslationSettingsTest.php @@ -133,7 +133,7 @@ function testSettingsUI() { // Test that language settings are correctly stored. $language_configuration = ContentLanguageSettings::loadByEntityTypeBundle('comment', 'comment_article'); - $this->assertEqual($language_configuration->getDefaultLangcode(), 'current_interface', 'The default language for article comments is set to the current interface language.'); + $this->assertEqual($language_configuration->getDefaultLangcode(), 'current_interface', 'The default language for article comments is set to the interface text language selected for page.'); $this->assertTrue($language_configuration->isLanguageAlterable(), 'The language selector for article comments is shown.'); // Verify language widget appears on comment type form. @@ -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/language.admin.js b/core/modules/language/language.admin.js index 0c14619..cea77c6 100644 --- a/core/modules/language/language.admin.js +++ b/core/modules/language/language.admin.js @@ -12,7 +12,7 @@ // Given a customization checkbox derive the language type being changed. function toggleTable(checkbox) { var $checkbox = $(checkbox); - // Get the language detection type such as User interface text language + // Get the language detection type such as Interface text language // detection or Content language detection. $checkbox.closest('.table-language-group') .find('table, .tabledrag-toggle-weight') diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 4e7f017..d5aafb6 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -296,8 +296,8 @@ function language_get_default_langcode($entity_type, $bundle) { function language_language_types_info() { 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.'), + 'name' => t('Interface text'), + 'description' => t('Order of language detection methods for interface text. If a translation of interface text is available in the detected language, it will be displayed.'), 'locked' => TRUE, ), LanguageInterface::TYPE_CONTENT => array( diff --git a/core/modules/language/src/Element/LanguageConfiguration.php b/core/modules/language/src/Element/LanguageConfiguration.php index aa6f94b..fc5263e 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('Interface text language selected for page'), 'authors_default' => t("Author's preferred language"), ); diff --git a/core/modules/language/src/Form/NegotiationConfigureForm.php b/core/modules/language/src/Form/NegotiationConfigureForm.php index da2574b..656fee0 100644 --- a/core/modules/language/src/Form/NegotiationConfigureForm.php +++ b/core/modules/language/src/Form/NegotiationConfigureForm.php @@ -236,7 +236,7 @@ protected function configureFormTable(array &$form, $type) { $configurable = $this->languageTypes->get('configurable'); $table_form['configurable'] = array( '#type' => 'checkbox', - '#title' => $this->t('Customize %language_name language detection to differ from User interface text language detection settings', array('%language_name' => $info['name'])), + '#title' => $this->t('Customize %language_name language detection to differ from Interface text language detection settings', array('%language_name' => $info['name'])), '#default_value' => in_array($type, $configurable), '#attributes' => array('class' => array('language-customization-checkbox')), '#attached' => array( diff --git a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUI.php b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUI.php index fd7eb75..3285b67 100644 --- a/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUI.php +++ b/core/modules/language/src/Plugin/LanguageNegotiation/LanguageNegotiationUI.php @@ -11,7 +11,8 @@ use Symfony\Component\HttpFoundation\Request; /** - * Class for identifying the language from the current interface language. + * Class for identifying the language from the interface text language selected + * for page. * * @Plugin( * id = Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUI::METHOD_ID, diff --git a/core/modules/language/tests/language_test/language_test.routing.yml b/core/modules/language/tests/language_test/language_test.routing.yml index a0464c5..489a7fe 100644 --- a/core/modules/language/tests/language_test/language_test.routing.yml +++ b/core/modules/language/tests/language_test/language_test.routing.yml @@ -29,5 +29,5 @@ language_test.entity_using_current_language: parameters: configurable_language: type: entity:configurable_language - # Force load in current interface language. + # Force load in the interface text language selected for page. with_config_overrides: TRUE diff --git a/core/modules/locale/src/Form/TranslateEditForm.php b/core/modules/locale/src/Form/TranslateEditForm.php index d953dce..44e86e7 100644 --- a/core/modules/locale/src/Form/TranslateEditForm.php +++ b/core/modules/locale/src/Form/TranslateEditForm.php @@ -131,7 +131,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { ); } if ($plurals == 2) { - // Simplify user interface text for the most common case. + // Simplify interface text for the most common case. $form['strings'][$string->lid]['translations'][1]['#title'] = $this->t('Plural form'); } } diff --git a/core/modules/system/core.api.php b/core/modules/system/core.api.php index 14c894a..c7c468e 100644 --- a/core/modules/system/core.api.php +++ b/core/modules/system/core.api.php @@ -384,7 +384,7 @@ * - Define a Cache ID (cid) value for your data. A cid is a string, which must * contain enough information to uniquely identify the data. For example, if * your data contains translated strings, then your cid value must include the - * current interface language. + * interface text language selected for page. * - Call the get() method to attempt a cache read, to see if the cache already * contains your data. * - If your data is not already in the cache, compute it and add it to the diff --git a/core/modules/views/src/Plugin/views/PluginBase.php b/core/modules/views/src/Plugin/views/PluginBase.php index 9c0f49b..8c1e31f 100644 --- a/core/modules/views/src/Plugin/views/PluginBase.php +++ b/core/modules/views/src/Plugin/views/PluginBase.php @@ -170,7 +170,7 @@ protected function defineOptions() { return array(); } * An array which describes the options of a plugin. Each element is an * associative array containing: * - default: The default value of one option. Should be translated to the - * current interface language if translatable. + * interface text language selected for page if translatable. * - (optional) contains: An array which describes the available options * under the key. If contains is set, the default will be ignored and * assumed to be an empty array. @@ -507,14 +507,19 @@ 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 currently-selected options in the list, if available. * * @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(). + * Only configurable languages and languages that are in $current_values are + * included in the list. */ - 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 +528,48 @@ 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 + // twice 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 d683426..1cdf0ef 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -2608,7 +2608,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 are 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/field/NumericField.php b/core/modules/views/src/Plugin/views/field/NumericField.php index 2034035..70622d1 100644 --- a/core/modules/views/src/Plugin/views/field/NumericField.php +++ b/core/modules/views/src/Plugin/views/field/NumericField.php @@ -113,7 +113,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) { ); } if ($plurals == 2) { - // Simplify user interface text for the most common case. + // Simplify interface text for the most common case. $form['format_plural_values'][0]['#description'] = $this->t('Text to use for the singular form, @count will be replaced with the value.'); $form['format_plural_values'][1]['#title'] = $this->t('Plural form'); $form['format_plural_values'][1]['#description'] = $this->t('Text to use for the plural form, @count will be replaced with the value.'); diff --git a/core/modules/views/src/Plugin/views/filter/LanguageFilter.php b/core/modules/views/src/Plugin/views/filter/LanguageFilter.php index 9826998..9396d0d 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 are 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]); + } } } }