diff --git a/core/modules/node/node.views.inc b/core/modules/node/node.views.inc index b4ef77c..9243adf 100644 --- a/core/modules/node/node.views.inc +++ b/core/modules/node/node.views.inc @@ -126,6 +126,25 @@ function node_views_data() { ), ); + if (\Drupal::moduleHandler()->moduleExists('language')) { + $data['node_field_data']['langcode'] = array( + 'title' => t('Translation language'), + 'help' => t('The language of the content or translation.'), + 'field' => array( + 'id' => 'node_language', + ), + 'filter' => array( + 'id' => 'language', + ), + 'argument' => array( + 'id' => 'language', + ), + 'sort' => array( + 'id' => 'standard', + ), + ); + } + $data['node_field_data']['status'] = array( 'title' => t('Published status'), 'help' => t('Whether or not the content is published.'), @@ -466,8 +485,8 @@ function node_views_data() { if (\Drupal::moduleHandler()->moduleExists('language')) { $data['node_revision']['langcode'] = array( - 'title' => t('Language'), - 'help' => t('The language the content is in.'), + 'title' => t('Original language'), + 'help' => t('The language the original content is in.'), 'field' => array( 'id' => 'node_language', ), @@ -564,7 +583,7 @@ function node_views_data() { $data['node_field_revision']['changed'] = array( 'title' => t('Updated date'), - 'help' => t('The date the node was last updated.'), + 'help' => t('The date the content was last updated.'), 'field' => array( 'id' => 'date', ), diff --git a/core/modules/node/src/Tests/Views/NodeLanguageTest.php b/core/modules/node/src/Tests/Views/NodeLanguageTest.php new file mode 100644 index 0000000..c832751 --- /dev/null +++ b/core/modules/node/src/Tests/Views/NodeLanguageTest.php @@ -0,0 +1,143 @@ +profile != 'standard') { + $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page')); + } + + // Add two new languages. + $language = new Language(array( + 'id' => 'fr', + 'name' => 'French', + )); + language_save($language); + + $language = new Language(array( + 'id' => 'es', + 'name' => 'Spanish', + )); + language_save($language); + + // Make the body field translatable. The title is already translatable by + // definition. + $field = FieldStorageConfig::loadByName('node', 'body'); + $field->translatable = TRUE; + $field->save(); + + // Set up node titles. They should not include the words "French", + // "English", or "Spanish", as there is a language field in the view + // that prints out those words. + $this->node_titles = array( + 'en' => array( + 'First node en', + 'Second node en', + ), + 'es' => array( + 'Primero nodo es', + 'Segundo nodo es', + ), + 'fr' => array( + 'Primier nodule fr', + ) + ); + + // Create nodes with translations. + foreach ($this->node_titles['en'] as $index => $title) { + $node = $this->drupalCreateNode(array('title' => $title, 'langcode' => 'en', 'type' => 'page')); + foreach (array('es', 'fr') as $langcode) { + if (isset($this->node_titles[$langcode][$index])) { + $translation = $node->addTranslation($langcode, array('title' => $this->node_titles[$langcode][$index])); + $translation->body->value = $this->randomName(32); + } + } + $node->save(); + } + } + + /** + * Tests translation language filter, field, and sort. + */ + public function testLanguages() { + // Test the page with no arguments. It is filtered to Spanish and French. + // The page shows node titles and languages. + $this->drupalGet('test-language'); + $message = 'French/Spanish page'; + + // Test that the correct nodes are shown. + foreach ($this->node_titles as $langcode => $list) { + foreach ($list as $title) { + if ($langcode == 'en') { + $this->assertNoText($title, $title . ' does not appear on ' . $message); + } + else { + $this->assertText($title, $title . ' does appear on ' . $message); + } + } + } + + // Test that the language field value is shown. + $this->assertNoText('English', 'English language is not shown on ' . $message); + $this->assertText('French', 'French language is shown on ' . $message); + $this->assertText('Spanish', 'Spanish language is shown on ' . $message); + + // Test page sorting, which is by language code, ascending. So the + // Spanish nodes should appear before the French nodes. + $page = $this->getTextContent(); + $pos_es_max = 0; + $pos_fr_min = 10000; + foreach ($this->node_titles['es'] as $title) { + $pos_es_max = max($pos_es_max, strpos($page, $title)); + } + foreach ($this->node_titles['fr'] as $title) { + $pos_fr_min = min($pos_fr_min, strpos($page, $title)); + } + $this->assertTrue($pos_es_max < $pos_fr_min, 'Spanish translations appear before French on ' . $message); + + // Test the argument -- filter to just Spanish. + $this->drupalGet('test-language/es'); + // This time, test just the language field. + $message = 'Spanish argument page'; + $this->assertNoText('English', 'English language is not shown on ' . $message); + $this->assertNoText('French', 'French language is not shown on ' . $message); + $this->assertText('Spanish', 'Spanish language is shown on ' . $message); + } +} 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 new file mode 100644 index 0000000..68fb2d5 --- /dev/null +++ b/core/modules/node/tests/modules/node_test_views/test_views/views.view.test_language.yml @@ -0,0 +1,314 @@ +uuid: 28125171-5b31-4943-9e00-ec0a9ceb0c1a +langcode: en +status: true +dependencies: + module: + - node +id: test_language +label: 'Test language' +module: views +description: '' +tag: '' +base_table: node +base_field: nid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + provider: views + display_options: + access: + type: perm + options: + perm: 'access content' + provider: user + dependencies: { } + cache: + type: none + options: { } + provider: views + dependencies: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: false + query_tags: { } + provider: views + dependencies: { } + exposed_form: + type: basic + options: + submit_button: Apply + reset_button: false + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: true + sort_asc_label: Asc + sort_desc_label: Desc + provider: views + dependencies: { } + pager: + type: none + options: + items_per_page: 0 + offset: 0 + style: + type: default + row: + type: fields + options: + default_field_elements: true + inline: { } + separator: '' + hide_empty: false + provider: views + fields: + title: + id: title + table: node_field_data + field: title + relationship: none + group_type: group + admin_label: '' + dependencies: + module: + - node + label: '' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: '' + word_boundary: false + ellipsis: false + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + link_to_node: 0 + provider: node + langcode: + id: langcode + table: node_field_data + field: langcode + relationship: none + group_type: group + admin_label: '' + dependencies: + module: + - node + label: Language + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: '' + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + link_to_node: false + native_language: 0 + plugin_id: node_language + provider: node + filters: + status: + value: true + table: node_field_data + field: status + provider: node + id: status + expose: + operator: '' + group: 1 + type: + id: type + table: node_field_data + field: type + value: + page: page + langcode: + id: langcode + table: node_field_data + field: langcode + relationship: none + group_type: group + admin_label: '' + dependencies: + module: + - views + - views + - views + - views + operator: in + value: + fr: fr + es: es + 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 + provider: views + sorts: + langcode: + id: langcode + table: node_field_data + field: langcode + relationship: none + group_type: group + admin_label: '' + dependencies: + module: + - views + - views + order: ASC + exposed: false + expose: + label: '' + plugin_id: standard + provider: views + title: 'Language filter test' + header: { } + footer: { } + empty: { } + relationships: { } + arguments: + langcode: + id: langcode + table: node_field_data + field: langcode + relationship: none + group_type: group + admin_label: '' + dependencies: + module: + - views + default_action: ignore + exception: + value: all + title_enable: false + title: All + title_enable: false + title: '' + default_argument_type: fixed + default_argument_options: + argument: '' + default_argument_skip_url: false + summary_options: + base_path: '' + count: true + items_per_page: 25 + override: false + summary: + sort_order: asc + number_of_records: 0 + format: default_summary + specify_validation: false + validate: + type: none + fail: 'not found' + validate_options: { } + plugin_id: language + provider: views + field_langcode: '***CURRENT_LANGUAGE***' + field_langcode_add_to_query: null + page_1: + display_plugin: page + id: page_1 + display_title: Page + position: 1 + provider: views + display_options: + field_langcode: '***CURRENT_LANGUAGE***' + field_langcode_add_to_query: null + path: test-language