updated core to 8.6.1 via composer

This commit is contained in:
2018-09-12 13:58:26 +02:00
parent a9a219f2ed
commit ea56b9fba3
4443 changed files with 112098 additions and 40708 deletions
@@ -3,7 +3,7 @@
* Content Translation admin behaviors.
*/
(function ($, Drupal, drupalSettings) {
(function($, Drupal, drupalSettings) {
/**
* Forces applicable options to be checked as translatable.
*
@@ -19,8 +19,12 @@
let $fields;
function fieldsChangeHandler($fields, dependentColumns) {
return function (e) {
Drupal.behaviors.contentTranslationDependentOptions.check($fields, dependentColumns, $(e.target));
return function(e) {
Drupal.behaviors.contentTranslationDependentOptions.check(
$fields,
dependentColumns,
$(e.target),
);
};
}
@@ -28,12 +32,15 @@
// that name and copy over the input values that require all columns to be
// translatable.
if (options && options.dependent_selectors) {
Object.keys(options.dependent_selectors).forEach((field) => {
Object.keys(options.dependent_selectors).forEach(field => {
$fields = $context.find(`input[name^="${field}"]`);
const dependentColumns = options.dependent_selectors[field];
$fields.on('change', fieldsChangeHandler($fields, dependentColumns));
Drupal.behaviors.contentTranslationDependentOptions.check($fields, dependentColumns);
Drupal.behaviors.contentTranslationDependentOptions.check(
$fields,
dependentColumns,
);
});
}
},
@@ -47,7 +54,7 @@
// A field that has many different translatable parts can also define one
// or more columns that require all columns to be translatable.
Object.keys(dependentColumns || {}).forEach((index) => {
Object.keys(dependentColumns || {}).forEach(index => {
column = dependentColumns[index];
if (!$changed) {
@@ -55,10 +62,11 @@
}
if ($element.is(`input[value="${column}"]:checked`)) {
$fields.prop('checked', true)
.not($element).prop('disabled', true);
}
else {
$fields
.prop('checked', true)
.not($element)
.prop('disabled', true);
} else {
$fields.prop('disabled', false);
}
});
@@ -77,50 +85,56 @@
attach(context) {
// Initially hide all field rows for non translatable bundles and all
// column rows for non translatable fields.
$(context).find('table .bundle-settings .translatable :input').once('translation-entity-admin-hide').each(function () {
const $input = $(this);
const $bundleSettings = $input.closest('.bundle-settings');
if (!$input.is(':checked')) {
$bundleSettings.nextUntil('.bundle-settings').hide();
}
else {
$bundleSettings
.nextUntil('.bundle-settings', '.field-settings')
.find('.translatable :input:not(:checked)')
.closest('.field-settings')
.nextUntil(':not(.column-settings)')
.hide();
}
});
$(context)
.find('table .bundle-settings .translatable :input')
.once('translation-entity-admin-hide')
.each(function() {
const $input = $(this);
const $bundleSettings = $input.closest('.bundle-settings');
if (!$input.is(':checked')) {
$bundleSettings.nextUntil('.bundle-settings').hide();
} else {
$bundleSettings
.nextUntil('.bundle-settings', '.field-settings')
.find('.translatable :input:not(:checked)')
.closest('.field-settings')
.nextUntil(':not(.column-settings)')
.hide();
}
});
// When a bundle is made translatable all of its fields should inherit
// this setting. Instead when it is made non translatable its fields are
// hidden, since their translatability no longer matters.
$('body').once('translation-entity-admin-bind').on('click', 'table .bundle-settings .translatable :input', (e) => {
const $target = $(e.target);
const $bundleSettings = $target.closest('.bundle-settings');
const $settings = $bundleSettings.nextUntil('.bundle-settings');
const $fieldSettings = $settings.filter('.field-settings');
if ($target.is(':checked')) {
$bundleSettings.find('.operations :input[name$="[language_alterable]"]').prop('checked', true);
$fieldSettings.find('.translatable :input').prop('checked', true);
$settings.show();
}
else {
$settings.hide();
}
})
.on('click', 'table .field-settings .translatable :input', (e) => {
$('body')
.once('translation-entity-admin-bind')
.on('click', 'table .bundle-settings .translatable :input', e => {
const $target = $(e.target);
const $bundleSettings = $target.closest('.bundle-settings');
const $settings = $bundleSettings.nextUntil('.bundle-settings');
const $fieldSettings = $settings.filter('.field-settings');
if ($target.is(':checked')) {
$bundleSettings
.find('.operations :input[name$="[language_alterable]"]')
.prop('checked', true);
$fieldSettings.find('.translatable :input').prop('checked', true);
$settings.show();
} else {
$settings.hide();
}
})
.on('click', 'table .field-settings .translatable :input', e => {
const $target = $(e.target);
const $fieldSettings = $target.closest('.field-settings');
const $columnSettings = $fieldSettings.nextUntil('.field-settings, .bundle-settings');
const $columnSettings = $fieldSettings.nextUntil(
'.field-settings, .bundle-settings',
);
if ($target.is(':checked')) {
$columnSettings.show();
}
else {
} else {
$columnSettings.hide();
}
});
},
};
}(jQuery, Drupal, drupalSettings));
})(jQuery, Drupal, drupalSettings);
@@ -65,7 +65,7 @@ function content_translation_field_sync_widget(FieldDefinitionInterface $field,
// does not get lost.
$element[key($options)]['#attached']['drupalSettings']['contentTranslationDependentOptions'] = [
'dependent_selectors' => [
$element_name => $require_all_groups_for_translation
$element_name => $require_all_groups_for_translation,
],
];
$element[key($options)]['#attached']['library'][] = 'content_translation/drupal.content_translation.admin';
@@ -164,6 +164,7 @@ function _content_translation_form_language_content_settings_form_alter(array &$
$form['#validate'][] = 'content_translation_form_language_content_settings_validate';
$form['#submit'][] = 'content_translation_form_language_content_settings_submit';
}
/**
* Checks whether translatability should be configurable for a field.
*
@@ -2,7 +2,7 @@ name: 'Content Translation'
type: module
description: 'Allows users to translate content entities.'
dependencies:
- language
- drupal:language
package: Multilingual
version: VERSION
core: 8.x
@@ -20,17 +20,17 @@ function content_translation_install() {
// Translation works when at least two languages are added.
if (count(\Drupal::languageManager()->getLanguages()) < 2) {
$t_args = [
':language_url' => Url::fromRoute('entity.configurable_language.collection')->toString()
':language_url' => Url::fromRoute('entity.configurable_language.collection')->toString(),
];
$message = t('This site has only a single language enabled. <a href=":language_url">Add at least one more language</a> in order to translate content.', $t_args);
drupal_set_message($message, 'warning');
\Drupal::messenger()->addWarning($message);
}
// Point the user to the content translation settings.
$t_args = [
':settings_url' => Url::fromRoute('language.content_settings_page')->toString()
':settings_url' => Url::fromRoute('language.content_settings_page')->toString(),
];
$message = t('<a href=":settings_url">Enable translation</a> for <em>content types</em>, <em>taxonomy vocabularies</em>, <em>accounts</em>, or any other element you wish to translate.', $t_args);
drupal_set_message($message, 'warning');
\Drupal::messenger()->addWarning($message);
}
/**
@@ -333,9 +333,11 @@ function content_translation_form_alter(array &$form, FormStateInterface $form_s
// Handle fields shared between translations when there is at least one
// translation available or a new one is being created.
if (!$entity->isNew() && (!isset($translations[$form_langcode]) || count($translations) > 1)) {
$langcode_key = $entity->getEntityType()->getKey('langcode');
foreach ($entity->getFieldDefinitions() as $field_name => $definition) {
if (isset($form[$field_name]) && $field_name != $langcode_key) {
// Allow the widget to define if it should be treated as multilingual
// by respecting an already set #multilingual key.
if (isset($form[$field_name]) && !isset($form[$field_name]['#multilingual'])) {
$form[$field_name]['#multilingual'] = $definition->isTranslatable();
}
}
@@ -0,0 +1,70 @@
id: d6_block_translation
label: Block translations
migration_tags:
- Drupal 6
- Configuration
- Multilingual
source:
plugin: d6_block_translation
constants:
dest_label: 'settings/label'
process:
langcode: language
property: constants/dest_label
translation: title
id:
-
plugin: migration_lookup
migration: d6_block
source:
- module
- delta
-
plugin: skip_on_empty
method: row
plugin:
-
plugin: static_map
bypass: true
source:
- module
- delta
map:
book:
0: book_navigation
comment:
0: views_block:comments_recent-block_1
forum:
0: forum_active_block
1: forum_new_block
locale:
0: language_block
node:
0: node_syndicate_block
search:
0: search_form_block
statistics:
0: statistics_popular_block
system:
0: system_powered_by_block
user:
0: user_login_block
1: system_menu_block:tools
2: views_block:who_s_new-block_1
3: views_block:who_s_online-who_s_online_block
-
plugin: block_plugin_id
-
plugin: skip_on_empty
method: row
theme:
plugin: block_theme
source:
- theme
- default_theme
- admin_theme
destination:
plugin: entity:block
migration_dependencies:
required:
- d6_block
@@ -0,0 +1,50 @@
id: d6_custom_block_translation
label: Custom block translations
migration_tags:
- Drupal 6
- Content
- Multilingual
source:
plugin: d6_box_translation
process:
id:
plugin: migration_lookup
migration: d6_custom_block
source:
- bid
langcode: language
info:
-
plugin: callback
source:
- title_translated
- title
callable: array_filter
-
plugin: callback
callable: current
'body/value':
-
plugin: callback
source:
- body_translated
- body
callable: array_filter
-
plugin: callback
callable: current
'body/format':
plugin: migration_lookup
migration: d6_filter_format
source: format
destination:
plugin: entity:block_content
no_stub: true
translations: true
destination_module: content_translation
migration_dependencies:
required:
- d6_filter_format
- block_content_body_field
- d6_custom_block
- language
@@ -0,0 +1,26 @@
id: d6_entity_reference_translation
label: Entity reference translations
migration_tags:
- Drupal 6
- Multilingual
- Follow-up migration
deriver: Drupal\migrate_drupal\Plugin\migrate\EntityReferenceTranslationDeriver
provider:
- content_translation
- migrate_drupal
# Supported target types for entity reference translation migrations. The array
# keys are the supported target types and the values are arrays of migrations
# to lookup for the translated entity IDs.
target_types:
node:
- d6_node_translation
# The source plugin will be set by the deriver.
source:
plugin: empty
key: default
target: default
# The process pipeline will be set by the deriver.
process: []
# The destination plugin will be set by the deriver.
destination:
plugin: null
@@ -0,0 +1,55 @@
id: d6_menu_links_translation
label: Menu links
migration_tags:
- Drupal 6
- Content
- Multilingual
source:
plugin: d6_menu_link_translation
process:
id: mlid
langcode: language
title:
-
plugin: callback
source:
- title_translated
- link_title
callable: array_filter
-
plugin: callback
callable: current
description:
-
plugin: callback
source:
- description_translated
- description
callable: array_filter
-
plugin: callback
callable: current
menu_name:
-
plugin: migration_lookup
# The menu migration is in the system module.
migration: d6_menu
source: menu_name
-
plugin: skip_on_empty
method: row
-
plugin: static_map
map:
management: admin
bypass: true
destination:
plugin: entity:menu_link_content
default_bundle: menu_link_content
no_stub: true
translations: true
migration_dependencies:
required:
- language
- d6_menu
- d6_menu_links
@@ -0,0 +1,59 @@
id: d6_node_translation
label: Node translations
migration_tags:
- Drupal 6
- translation
- Content
- Multilingual
class: Drupal\node\Plugin\migrate\D6NodeTranslation
deriver: Drupal\node\Plugin\migrate\D6NodeDeriver
source:
plugin: d6_node
translations: true
process:
# If you are using this file to build a custom migration consider removing
# the nid field to allow incremental migrations.
nid: tnid
type: type
langcode:
plugin: default_value
source: language
default_value: "und"
title: title
uid: node_uid
status: status
created: created
changed: changed
promote: promote
sticky: sticky
'body/format':
plugin: migration_lookup
migration: d6_filter_format
source: format
'body/value': body
'body/summary': teaser
revision_uid: revision_uid
revision_log: log
revision_timestamp: timestamp
content_translation_source: source_langcode
# unmapped d6 fields.
# translate
# moderate
# comment
destination:
plugin: entity:node
translations: true
destination_module: content_translation
migration_dependencies:
required:
- d6_user
- d6_node_type
- d6_node_settings
- d6_filter_format
- language
optional:
- d6_field_instance_widget_settings
- d6_field_formatter_settings
- d6_upload_field_instance
@@ -3,6 +3,7 @@ label: Taxonomy terms
migration_tags:
- Drupal 6
- Content
- Multilingual
source:
plugin: d6_taxonomy_term
translations: true
@@ -34,6 +35,7 @@ process:
changed: timestamp
destination:
plugin: entity:taxonomy_term
destination_module: content_translation
migration_dependencies:
required:
- d6_taxonomy_vocabulary
@@ -0,0 +1,26 @@
id: d7_entity_reference_translation
label: Entity reference translations
migration_tags:
- Drupal 7
- Multilingual
- Follow-up migration
deriver: Drupal\migrate_drupal\Plugin\migrate\EntityReferenceTranslationDeriver
provider:
- content_translation
- migrate_drupal
# Supported target types for entity reference translation migrations. The array
# keys are the supported target types and the values are arrays of migrations
# to lookup for the translated entity IDs.
target_types:
node:
- d7_node_translation
# The source plugin will be set by the deriver.
source:
plugin: empty
key: default
target: default
# The process pipeline will be set by the deriver.
process: []
# The destination plugin will be set by the deriver.
destination:
plugin: null
@@ -0,0 +1,37 @@
id: d7_entity_translation_settings
label: Drupal 7 Entity Translation settings
migration_tags:
- Drupal 7
- Configuration
- Multilingual
source:
plugin: d7_entity_translation_settings
process:
id: id
target_entity_type_id: target_entity_type_id
target_bundle: target_bundle
default_langcode:
plugin: static_map
source: default_langcode
bypass: true
map:
xx-et-default: site_default
xx-et-current: current_interface
xx-et-author: authors_default
language_alterable: language_alterable
third_party_settings/content_translation/enabled:
plugin: default_value
default_value: true
third_party_settings/content_translation/bundle_settings/untranslatable_fields_hide: untranslatable_fields_hide
destination:
plugin: entity:language_content_settings
content_translation_update_definitions:
- comment
- node
- taxonomy_term
- user
migration_dependencies:
optional:
- d7_comment_type
- d7_node_type
- d7_taxonomy_vocabulary
@@ -0,0 +1,45 @@
id: d7_node_translation
label: Node translations
migration_tags:
- Drupal 7
- translation
- Content
- Multilingual
class: Drupal\node\Plugin\migrate\D7NodeTranslation
deriver: Drupal\node\Plugin\migrate\D7NodeDeriver
source:
plugin: d7_node
translations: true
process:
# If you are using this file to build a custom migration consider removing
# the nid field to allow incremental migrations.
nid: tnid
type: type
langcode:
plugin: default_value
source: language
default_value: "und"
title: title
uid: node_uid
status: status
created: created
changed: changed
promote: promote
sticky: sticky
revision_uid: revision_uid
revision_log: log
revision_timestamp: timestamp
content_translation_source: source_langcode
destination:
plugin: entity:node
translations: true
content_translation_update_definitions:
- node
destination_module: content_translation
migration_dependencies:
required:
- d7_user
- d7_node_type
- language
optional:
- d7_field_instance
@@ -0,0 +1,27 @@
id: d7_user_entity_translation
label: User accounts entity translations
migration_tags:
- Drupal 7
- translation
- Content
- Multilingual
class: Drupal\user\Plugin\migrate\User
source:
plugin: d7_user_entity_translation
process:
uid: entity_id
langcode: language
content_translation_source: source
content_translation_uid: uid
content_translation_status: status
content_translation_outdated: translate
content_translation_created: created
destination:
plugin: entity:user
translations: true
destination_module: content_translation
migration_dependencies:
required:
- language
- d7_entity_translation_settings
- d7_user
@@ -0,0 +1,120 @@
id: node_translation_menu_links
label: Node Translations Menu links
audit: true
migration_tags:
- Drupal 6
- Drupal 7
- Content
- Multilingual
source:
plugin: menu_link
constants:
entity_prefix: 'entity:'
node_prefix: 'node/'
process:
id: mlid
title: link_title
description: description
menu_name:
-
plugin: migration_lookup
# The menu migration is in the system module.
migration:
- d6_menu
- d7_menu
source: menu_name
-
plugin: skip_on_empty
method: row
-
plugin: static_map
map:
management: admin
bypass: true
# In this process pipeline, given a menu link path that might be for a
# translated node which has been merged with the default language node, we are
# trying to determine the new node ID, that is the ID of the default language
# node.
new_nid:
-
# If the path is of the form "node/<ID>" and is not routed, we will get
# back an URI of the form "base:node/<ID>".
plugin: link_uri
source:
- link_path
validate_route: false
-
# Isolate the node ID.
plugin: explode
delimiter: 'base:node/'
-
# Extract the node ID.
plugin: extract
default: false
index:
- 1
-
# Skip row if node ID is empty.
plugin: skip_on_empty
method: row
-
# With the old node ID in hand, lookup in the d6_node_translation or
# d7_node_translation mapping tables to find the new node ID.
plugin: migration_lookup
migration:
- d6_node_translation
- d7_node_translation
no_stub: true
-
# Skip row if the new node ID is empty.
plugin: skip_on_empty
method: row
-
# Extract the node ID. The migration lookup will return an array with two
# items, the new node ID and the translation langcode. We need the node ID
# which is at index 0.
plugin: extract
index:
- 0
# This will be used in the "link/uri" and "route" processes below.
link_path:
plugin: concat
source:
- 'constants/node_prefix'
- '@new_nid'
link/uri:
plugin: concat
source:
- 'constants/entity_prefix'
- '@link_path'
link/options: options
route:
plugin: route
source:
- '@link_path'
- options
route_name: '@route/route_name'
route_parameters: '@route/route_parameters'
url: '@route/url'
options: '@route/options'
external: external
weight: weight
expanded: expanded
enabled: enabled
parent:
plugin: menu_link_parent
source:
- plid
- '@menu_name'
- parent_link_path
changed: updated
destination:
plugin: entity:menu_link_content
default_bundle: menu_link_content
no_stub: true
migration_dependencies:
optional:
- d6_menu_links
- d6_node_translation
- d7_menu_links
- d7_node_translation
@@ -0,0 +1,35 @@
id: statistics_node_translation_counter
label: Node translation counter
migration_tags:
- Drupal 6
- Drupal 7
- Content
- Multilingual
source:
plugin: node_counter
process:
nid:
-
plugin: migration_lookup
migration:
- d6_node_translation
- d7_node_translation
source: nid
-
plugin: skip_on_empty
method: row
-
plugin: extract
index:
- 0
totalcount: totalcount
daycount: daycount
timestamp: timestamp
destination:
plugin: node_counter
migration_dependencies:
required:
- statistics_node_counter
optional:
- d6_node_translation
- d7_node_translation
@@ -512,10 +512,6 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface, E
'#default_value' => $new_translation || !$date ? '' : format_date($date, 'custom', 'Y-m-d H:i:s O'),
];
if (isset($language_widget)) {
$language_widget['#multilingual'] = TRUE;
}
$form['#process'][] = [$this, 'entityFormSharedElements'];
}
@@ -734,7 +730,7 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface, E
'target' => $form_object->getFormLangcode($form_state),
]);
$languages = $this->languageManager->getLanguages();
drupal_set_message(t('Source language set to: %language', ['%language' => $languages[$source]->getName()]));
$this->messenger->addStatus(t('Source language set to: %language', ['%language' => $languages[$source]->getName()]));
}
/**
@@ -743,10 +739,10 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface, E
* Takes care of entity deletion.
*/
public function entityFormDelete($form, FormStateInterface $form_state) {
$form_object = $form_state->getFormObject()->getEntity();
$form_object = $form_state->getFormObject();
$entity = $form_object->getEntity();
if (count($entity->getTranslationLanguages()) > 1) {
drupal_set_message(t('This will delete all the translations of %label.', ['%label' => $entity->label()]), 'warning');
$this->messenger->addWarning(t('This will delete all the translations of %label.', ['%label' => $entity->label()]));
}
}
@@ -202,7 +202,7 @@ class FieldTranslationSynchronizer implements FieldTranslationSynchronizerInterf
/**
* {@inheritdoc}
*/
public function synchronizeItems(array &$values, array $unchanged_items, $sync_langcode, array $translations, array $columns) {
public function synchronizeItems(array &$values, array $unchanged_items, $sync_langcode, array $translations, array $properties) {
$source_items = $values[$sync_langcode];
// Make sure we can detect any change in the source items.
@@ -218,7 +218,7 @@ class FieldTranslationSynchronizer implements FieldTranslationSynchronizerInterf
// for each column.
for ($delta = 0; $delta < $total; $delta++) {
foreach (['old' => $unchanged_items, 'new' => $source_items] as $key => $items) {
if ($item_id = $this->itemHash($items, $delta, $columns)) {
if ($item_id = $this->itemHash($items, $delta, $properties)) {
$change_map[$item_id][$key][] = $delta;
}
}
@@ -251,7 +251,7 @@ class FieldTranslationSynchronizer implements FieldTranslationSynchronizerInterf
$old_delta = NULL;
$new_delta = NULL;
if ($item_id = $this->itemHash($source_items, $delta, $columns)) {
if ($item_id = $this->itemHash($source_items, $delta, $properties)) {
if (!empty($change_map[$item_id]['old'])) {
$old_delta = array_shift($change_map[$item_id]['old']);
}
@@ -272,7 +272,7 @@ class FieldTranslationSynchronizer implements FieldTranslationSynchronizerInterf
// items and the other columns from the existing values. This only
// works if the delta exists in the language.
elseif ($created && !empty($original_field_values[$langcode][$delta])) {
$values[$langcode][$delta] = $this->createMergedItem($source_items[$delta], $original_field_values[$langcode][$delta], $columns);
$values[$langcode][$delta] = $this->createMergedItem($source_items[$delta], $original_field_values[$langcode][$delta], $properties);
}
// If the delta doesn't exist, copy from the source language.
elseif ($created) {
@@ -290,7 +290,7 @@ class FieldTranslationSynchronizer implements FieldTranslationSynchronizerInterf
// we may have desynchronized field values, so we make sure that
// untranslatable properties are synchronized, even if in any other
// situation this would not be necessary.
$values[$langcode][$new_delta] = $this->createMergedItem($source_items[$new_delta], $item, $columns);
$values[$langcode][$new_delta] = $this->createMergedItem($source_items[$new_delta], $item, $properties);
}
}
}
@@ -324,19 +324,19 @@ class FieldTranslationSynchronizer implements FieldTranslationSynchronizerInterf
* An array of field items.
* @param int $delta
* The delta identifying the item to be processed.
* @param array $columns
* @param array $properties
* An array of column names to be synchronized.
*
* @returns string
* A hash code that can be used to identify the item.
*/
protected function itemHash(array $items, $delta, array $columns) {
protected function itemHash(array $items, $delta, array $properties) {
$values = [];
if (isset($items[$delta])) {
foreach ($columns as $column) {
if (!empty($items[$delta][$column])) {
$value = $items[$delta][$column];
foreach ($properties as $property) {
if (!empty($items[$delta][$property])) {
$value = $items[$delta][$property];
// String and integer values are by far the most common item values,
// thus we special-case them to improve performance.
$values[] = is_string($value) || is_int($value) ? $value : hash('sha256', serialize($value));
@@ -50,10 +50,10 @@ interface FieldTranslationSynchronizerInterface {
* The language code of the items to use as source values.
* @param array $translations
* An array of all the available language codes for the given field.
* @param array $columns
* An array of column names to be synchronized.
* @param array $properties
* An array of property names to be synchronized.
*/
public function synchronizeItems(array &$field_values, array $unchanged_items, $sync_langcode, array $translations, array $columns);
public function synchronizeItems(array &$field_values, array $unchanged_items, $sync_langcode, array $translations, array $properties);
/**
* Returns the synchronized properties for the specified field definition.
@@ -0,0 +1,198 @@
<?php
namespace Drupal\content_translation\Plugin\migrate\source\d7;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 7 Entity Translation settings from variables.
*
* @MigrateSource(
* id = "d7_entity_translation_settings",
* source_module = "entity_translation"
* )
*/
class EntityTranslationSettings extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
// Query all meaningful variables for entity translation.
$query = $this->select('variable', 'v')
->fields('v', ['name', 'value']);
$condition = $query->orConditionGroup()
// The 'entity_translation_entity_types' variable tells us which entity
// type uses entity translation.
->condition('name', 'entity_translation_entity_types')
// The 'entity_translation_taxonomy' variable tells us which taxonomy
// vocabulary uses entity_translation.
->condition('name', 'entity_translation_taxonomy')
// The 'entity_translation_settings_%' variables give us the entity
// translation settings for each entity type and each bundle.
->condition('name', 'entity_translation_settings_%', 'LIKE')
// The 'language_content_type_%' variables tells us which node type and
// which comment type uses entity translation.
->condition('name', 'language_content_type_%', 'LIKE');
$query->condition($condition);
return $query;
}
/**
* {@inheritdoc}
*/
protected function initializeIterator() {
$results = array_map('unserialize', $this->prepareQuery()->execute()->fetchAllKeyed());
$rows = [];
// Find out which entity type uses entity translation by looking at the
// 'entity_translation_entity_types' variable.
$entity_types = array_filter($results['entity_translation_entity_types']);
// If no entity type uses entity translation, there's nothing to do.
if (empty($entity_types)) {
return new \ArrayIterator($rows);
}
// Find out which node type uses entity translation by looking at the
// 'language_content_type_%' variables.
$node_types = [];
foreach ($results as $name => $value) {
if (preg_match('/^language_content_type_(.+)$/', $name, $matches) && (int) $value === 4) {
$node_types[] = $matches[1];
}
}
// Find out which vocabulary uses entity translation by looking at the
// 'entity_translation_taxonomy' variable.
$vocabularies = [];
if (isset($results['entity_translation_taxonomy']) && is_array($results['entity_translation_taxonomy'])) {
$vocabularies = array_keys(array_filter($results['entity_translation_taxonomy']));
}
if (in_array('node', $entity_types, TRUE) && !empty($node_types)) {
// For each node type that uses entity translation, check if a
// settings variable exists for that node type, otherwise use default
// values.
foreach ($node_types as $node_type) {
$settings = isset($results['entity_translation_settings_node__' . $node_type]) ? $results['entity_translation_settings_node__' . $node_type] : [];
$rows[] = [
'id' => 'node.' . $node_type,
'target_entity_type_id' => 'node',
'target_bundle' => $node_type,
'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'und',
// The Drupal 7 'hide_language_selector' configuration has become
// 'language_alterable' in Drupal 8 so we need to negate the value we
// receive from the source. The Drupal 7 'hide_language_selector'
// default value for the node entity type was FALSE so in Drupal 8 it
// should be set to TRUE, unlike the other entity types for which
// it's the opposite.
'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : TRUE,
'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE,
];
}
}
if (in_array('comment', $entity_types, TRUE) && !empty($node_types)) {
// A comment type uses entity translation if the associated node type
// uses it. So, for each node type that uses entity translation, check
// if a settings variable exists for that comment type, otherwise use
// default values.
foreach ($node_types as $node_type) {
$settings = isset($results['entity_translation_settings_comment__comment_node_' . $node_type]) ? $results['entity_translation_settings_comment__comment_node_' . $node_type] : [];
// Forum uses a hardcoded comment type name, so make sure we use it
// when we're dealing with forum comment type.
$bundle = $node_type == 'forum' ? 'comment_forum' : 'comment_node_' . $node_type;
$rows[] = [
'id' => 'comment.' . $bundle,
'target_entity_type_id' => 'comment',
'target_bundle' => $bundle,
'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'xx-et-current',
// The Drupal 7 'hide_language_selector' configuration has become
// 'language_alterable' in Drupal 8 so we need to negate the value we
// receive from the source. The Drupal 7 'hide_language_selector'
// default value for the comment entity type was TRUE so in Drupal 8
// it should be set to FALSE.
'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : FALSE,
'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE,
];
}
}
if (in_array('taxonomy_term', $entity_types, TRUE) && !empty($vocabularies)) {
// For each vocabulary that uses entity translation, check if a
// settings variable exists for that vocabulary, otherwise use default
// values.
foreach ($vocabularies as $vocabulary) {
$settings = isset($results['entity_translation_settings_taxonomy_term__' . $vocabulary]) ? $results['entity_translation_settings_taxonomy_term__' . $vocabulary] : [];
$rows[] = [
'id' => 'taxonomy_term.' . $vocabulary,
'target_entity_type_id' => 'taxonomy_term',
'target_bundle' => $vocabulary,
'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'xx-et-default',
// The Drupal 7 'hide_language_selector' configuration has become
// 'language_alterable' in Drupal 8 so we need to negate the value we
// receive from the source. The Drupal 7 'hide_language_selector'
// default value for the taxonomy_term entity type was TRUE so in
// Drupal 8 it should be set to FALSE.
'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : FALSE,
'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE,
];
}
}
if (in_array('user', $entity_types, TRUE)) {
// User entity type is not bundleable. Check if a settings variable
// exists, otherwise use default values.
$settings = isset($results['entity_translation_settings_user__user']) ? $results['entity_translation_settings_user__user'] : [];
$rows[] = [
'id' => 'user.user',
'target_entity_type_id' => 'user',
'target_bundle' => 'user',
'default_langcode' => isset($settings['default_language']) ? $settings['default_language'] : 'xx-et-default',
// The Drupal 7 'hide_language_selector' configuration has become
// 'language_alterable' in Drupal 8 so we need to negate the value we
// receive from the source. The Drupal 7 'hide_language_selector'
// default value for the user entity type was TRUE so in Drupal 8 it
// should be set to FALSE.
'language_alterable' => isset($settings['hide_language_selector']) ? (bool) !$settings['hide_language_selector'] : FALSE,
'untranslatable_fields_hide' => isset($settings['shared_fields_original_only']) ? (bool) $settings['shared_fields_original_only'] : FALSE,
];
}
return new \ArrayIterator($rows);
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'id' => $this->t('The configuration ID'),
'target_entity_type_id' => $this->t('The target entity type ID'),
'target_bundle' => $this->t('The target bundle'),
'default_langcode' => $this->t('The default language'),
'language_alterable' => $this->t('Whether to show language selector on create and edit pages'),
'untranslatable_fields_hide' => $this->t('Whether to hide non translatable fields on translation forms'),
];
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['id']['type'] = 'string';
return $ids;
}
/**
* {@inheritdoc}
*/
public function count($refresh = FALSE) {
// Since the number of variables we fetch with query() does not match the
// actual number of rows generated by initializeIterator(), we need to
// override count() to return the correct count.
return (int) $this->initializeIterator()->count();
}
}
@@ -9,7 +9,7 @@ use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\system\Tests\Cache\AssertPageCacheContextsAndTagsTrait;
/**
@@ -37,8 +37,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
protected $testLanguageSelector = TRUE;
/**
* Flag that tells whether the HTML escaping of all languages works or not
* after SafeMarkup change.
* Flag to determine if "all languages" rendering is tested.
*
* @var bool
*/
@@ -113,12 +112,11 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(),
'source' => $default_langcode,
'target' => $langcode
'target' => $langcode,
], ['language' => $language]);
$this->drupalPostForm($add_url, $this->getEditValues($values, $langcode), $this->getFormSubmitActionForNewTranslation($entity, $langcode));
// Assert that HTML is escaped in "all languages" in UI after SafeMarkup
// change.
// Assert that HTML is not escaped unexpectedly.
if ($this->testHTMLEscapeForAllLanguages) {
$this->assertNoRaw('&lt;span class=&quot;translation-entity-all-languages&quot;&gt;(all languages)&lt;/span&gt;');
$this->assertRaw('<span class="translation-entity-all-languages">(all languages)</span>');
@@ -141,10 +139,10 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$author_field_name = $entity->hasField('content_translation_uid') ? 'content_translation_uid' : 'uid';
if ($entity->getFieldDefinition($author_field_name)->isTranslatable()) {
$this->assertEqual($metadata_target_translation->getAuthor()->id(), $this->translator->id(),
SafeMarkup::format('Author of the target translation @langcode correctly stored for translatable owner field.', ['@langcode' => $langcode]));
new FormattableMarkup('Author of the target translation @langcode correctly stored for translatable owner field.', ['@langcode' => $langcode]));
$this->assertNotEqual($metadata_target_translation->getAuthor()->id(), $metadata_source_translation->getAuthor()->id(),
SafeMarkup::format('Author of the target translation @target different from the author of the source translation @source for translatable owner field.',
new FormattableMarkup('Author of the target translation @target different from the author of the source translation @source for translatable owner field.',
['@target' => $langcode, '@source' => $default_langcode]));
}
else {
@@ -154,7 +152,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$created_field_name = $entity->hasField('content_translation_created') ? 'content_translation_created' : 'created';
if ($entity->getFieldDefinition($created_field_name)->isTranslatable()) {
$this->assertTrue($metadata_target_translation->getCreatedTime() > $metadata_source_translation->getCreatedTime(),
SafeMarkup::format('Translation creation timestamp of the target translation @target is newer than the creation timestamp of the source translation @source for translatable created field.',
new FormattableMarkup('Translation creation timestamp of the target translation @target is newer than the creation timestamp of the source translation @source for translatable created field.',
['@target' => $langcode, '@source' => $default_langcode]));
}
else {
@@ -178,7 +176,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(),
'source' => $default_langcode,
'target' => $langcode
'target' => $langcode,
], ['language' => $language]);
// This does not save anything, it merely reloads the form and fills in the
// fields with the values from the different source language.
@@ -192,7 +190,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(),
'source' => $source_langcode,
'target' => $langcode
'target' => $langcode,
], ['language' => $language]);
$this->drupalPostForm($add_url, $edit, $this->getFormSubmitActionForNewTranslation($entity, $langcode));
$storage->resetCache([$this->entityId]);
@@ -5,6 +5,6 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- content_translation
- language
- entity_test
- drupal:content_translation
- drupal:language
- drupal:entity_test
@@ -5,5 +5,5 @@ package: Testing
version: VERSION
core: 8.x
dependencies:
- content_translation
- views
- drupal:content_translation
- drupal:views
@@ -140,7 +140,7 @@ class ContentTranslationLanguageChangeTest extends NodeTestBase {
$this->assertRaw('<title>Edit Article english_title | Drupal</title>');
$edit = [
'langcode[0][value]' => 'en',
'field_image_field[0][alt]' => 'alternative_text'
'field_image_field[0][alt]' => 'alternative_text',
];
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
@@ -98,14 +98,14 @@ class ContentTranslationOperationsTest extends NodeTestBase {
'access content' => TRUE,
]
);
$node->setPublished(FALSE)->save();
$node->setUnpublished()->save();
$this->drupalGet($node->urlInfo('drupal:content-translation-overview'));
$this->assertResponse(403);
$this->drupalLogout();
// Ensure the 'Translate' local task does not show up anymore when disabling
// translations for a content type.
$node->setPublished(TRUE)->save();
$node->setPublished()->save();
user_role_change_permissions(
Role::AUTHENTICATED_ID,
[
@@ -136,7 +136,7 @@ class ContentTranslationOperationsTest extends NodeTestBase {
$this->assertFalse(content_translation_translate_access($node)->isAllowed());
$access_control_handler->resetCache();
$node->setPublished(TRUE);
$node->setPublished();
$node->save();
$this->assertTrue(content_translation_translate_access($node)->isAllowed());
$access_control_handler->resetCache();
@@ -3,6 +3,7 @@
namespace Drupal\Tests\content_translation\Functional;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Tests\content_moderation\Traits\ContentModerationTestTrait;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
/**
@@ -11,6 +12,7 @@ use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
abstract class ContentTranslationPendingRevisionTestBase extends ContentTranslationTestBase {
use ContentTypeCreationTrait;
use ContentModerationTestTrait;
/**
* {@inheritdoc}
@@ -110,6 +112,7 @@ abstract class ContentTranslationPendingRevisionTestBase extends ContentTranslat
protected function setupBundle() {
parent::setupBundle();
$this->createContentType(['type' => $this->bundle]);
$this->createEditorialWorkflow();
}
/**
@@ -124,6 +127,9 @@ abstract class ContentTranslationPendingRevisionTestBase extends ContentTranslat
* The active revision translation or NULL if none could be identified.
*/
protected function loadRevisionTranslation(ContentEntityInterface $entity, $langcode) {
// Explicitly invalidate the cache for that node, as the call below is
// statically cached.
$this->storage->resetCache([$entity->id()]);
$revision_id = $this->storage->getLatestTranslationAffectedRevisionId($entity->id(), $langcode);
/** @var \Drupal\Core\Entity\ContentEntityInterface $revision */
$revision = $revision_id ? $this->storage->loadRevision($revision_id) : NULL;
@@ -154,7 +154,7 @@ class ContentTranslationSettingsTest extends BrowserTestBase {
'settings[node][article][settings][language][langcode]' => 'current_interface',
'settings[node][article][settings][language][language_alterable]' => TRUE,
'settings[node][article][translatable]' => TRUE,
'settings[node][article][fields][title]' => TRUE
'settings[node][article][fields][title]' => TRUE,
];
$this->assertSettings('node', NULL, TRUE, $edit);
@@ -25,7 +25,7 @@ class ContentTranslationUISkipTest extends BrowserTestBase {
$admin_user = $this->drupalCreateUser([
'translate any entity',
'administer content translation',
'administer languages'
'administer languages',
]);
$this->drupalLogin($admin_user);
// Visit the content translation.
@@ -10,7 +10,6 @@ use Drupal\Core\Language\Language;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
/**
@@ -35,8 +34,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
protected $testLanguageSelector = TRUE;
/**
* Flag that tells whether the HTML escaping of all languages works or not
* after SafeMarkup change.
* Flag to determine if "all languages" rendering is tested.
*
* @var bool
*/
@@ -111,12 +109,11 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(),
'source' => $default_langcode,
'target' => $langcode
'target' => $langcode,
], ['language' => $language]);
$this->drupalPostForm($add_url, $this->getEditValues($values, $langcode), $this->getFormSubmitActionForNewTranslation($entity, $langcode));
// Assert that HTML is escaped in "all languages" in UI after SafeMarkup
// change.
// Assert that HTML is not escaped unexpectedly.
if ($this->testHTMLEscapeForAllLanguages) {
$this->assertNoRaw('&lt;span class=&quot;translation-entity-all-languages&quot;&gt;(all languages)&lt;/span&gt;');
$this->assertRaw('<span class="translation-entity-all-languages">(all languages)</span>');
@@ -139,10 +136,10 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$author_field_name = $entity->hasField('content_translation_uid') ? 'content_translation_uid' : 'uid';
if ($entity->getFieldDefinition($author_field_name)->isTranslatable()) {
$this->assertEqual($metadata_target_translation->getAuthor()->id(), $this->translator->id(),
SafeMarkup::format('Author of the target translation @langcode correctly stored for translatable owner field.', ['@langcode' => $langcode]));
new FormattableMarkup('Author of the target translation @langcode correctly stored for translatable owner field.', ['@langcode' => $langcode]));
$this->assertNotEqual($metadata_target_translation->getAuthor()->id(), $metadata_source_translation->getAuthor()->id(),
SafeMarkup::format('Author of the target translation @target different from the author of the source translation @source for translatable owner field.',
new FormattableMarkup('Author of the target translation @target different from the author of the source translation @source for translatable owner field.',
['@target' => $langcode, '@source' => $default_langcode]));
}
else {
@@ -152,7 +149,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$created_field_name = $entity->hasField('content_translation_created') ? 'content_translation_created' : 'created';
if ($entity->getFieldDefinition($created_field_name)->isTranslatable()) {
$this->assertTrue($metadata_target_translation->getCreatedTime() > $metadata_source_translation->getCreatedTime(),
SafeMarkup::format('Translation creation timestamp of the target translation @target is newer than the creation timestamp of the source translation @source for translatable created field.',
new FormattableMarkup('Translation creation timestamp of the target translation @target is newer than the creation timestamp of the source translation @source for translatable created field.',
['@target' => $langcode, '@source' => $default_langcode]));
}
else {
@@ -176,7 +173,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(),
'source' => $default_langcode,
'target' => $langcode
'target' => $langcode,
], ['language' => $language]);
// This does not save anything, it merely reloads the form and fills in the
// fields with the values from the different source language.
@@ -190,7 +187,7 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase {
$add_url = Url::fromRoute("entity.$entity_type_id.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(),
'source' => $source_langcode,
'target' => $langcode
'target' => $langcode,
], ['language' => $language]);
$this->drupalPostForm($add_url, $edit, $this->getFormSubmitActionForNewTranslation($entity, $langcode));
$storage->resetCache([$this->entityId]);
@@ -3,6 +3,8 @@
namespace Drupal\Tests\content_translation\Functional;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
/**
@@ -12,6 +14,11 @@ use Drupal\language\Entity\ConfigurableLanguage;
*/
class ContentTranslationUntranslatableFieldsTest extends ContentTranslationPendingRevisionTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['field_test'];
/**
* {@inheritdoc}
*/
@@ -32,6 +39,32 @@ class ContentTranslationUntranslatableFieldsTest extends ContentTranslationPendi
$this->assertFalse($definitions[$this->fieldName]->isTranslatable());
}
/**
* {@inheritdoc}
*/
protected function setupTestFields() {
parent::setupTestFields();
$field_storage = FieldStorageConfig::create([
'field_name' => 'field_multilingual',
'type' => 'test_field',
'entity_type' => $this->entityTypeId,
'cardinality' => 1,
]);
$field_storage->save();
FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => $this->bundle,
'label' => 'Untranslatable-but-visible test field',
'translatable' => FALSE,
])->save();
entity_get_form_display($this->entityTypeId, $this->bundle, 'default')
->setComponent('field_multilingual', [
'type' => 'test_field_widget_multilingual',
])
->save();
}
/**
* Tests that hiding untranslatable field widgets works correctly.
*/
@@ -52,6 +85,7 @@ class ContentTranslationUntranslatableFieldsTest extends ContentTranslationPendi
$this->assertNotEmpty($this->xpath($field_xpath));
$clue_xpath = '//label[@for="edit-' . strtr($this->fieldName, '_', '-') . '-0-value"]/span[text()="(all languages)"]';
$this->assertEmpty($this->xpath($clue_xpath));
$this->assertSession()->pageTextContains('Untranslatable-but-visible test field');
// Add a translation and check that the untranslatable field widget is
// displayed on the translation and edit forms along with translatability
@@ -59,11 +93,12 @@ class ContentTranslationUntranslatableFieldsTest extends ContentTranslationPendi
$add_url = Url::fromRoute("entity.{$this->entityTypeId}.content_translation_add", [
$entity->getEntityTypeId() => $entity->id(),
'source' => 'en',
'target' => 'it'
'target' => 'it',
]);
$this->drupalGet($add_url);
$this->assertNotEmpty($this->xpath($field_xpath));
$this->assertNotEmpty($this->xpath($clue_xpath));
$this->assertSession()->pageTextContains('Untranslatable-but-visible test field');
$this->drupalPostForm(NULL, [], 'Save');
// Check that the widget is displayed along with its clue in the edit form
@@ -88,11 +123,13 @@ class ContentTranslationUntranslatableFieldsTest extends ContentTranslationPendi
$field_xpath = '//input[@name="' . $this->fieldName . '[0][value]"]';
$this->assertNotEmpty($this->xpath($field_xpath));
$this->assertEmpty($this->xpath($clue_xpath));
$this->assertSession()->pageTextContains('Untranslatable-but-visible test field');
// Verify no widget is displayed on the non-default language edit form.
$this->drupalGet($it_edit_url);
$this->assertEmpty($this->xpath($field_xpath));
$this->assertEmpty($this->xpath($clue_xpath));
$this->assertSession()->pageTextContains('Untranslatable-but-visible test field');
// Verify a warning is displayed.
$this->assertSession()->pageTextContains('Fields that apply to all languages are hidden to avoid conflicting changes.');
@@ -2,7 +2,7 @@
namespace Drupal\Tests\content_translation\Functional;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Url;
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
@@ -161,19 +161,19 @@ class ContentTranslationWorkflowsTest extends ContentTranslationTestBase {
// Check whether the user is allowed to access the entity form in edit mode.
$edit_url = $this->entity->urlInfo('edit-form', $options);
$this->drupalGet($edit_url, $options);
$this->assertResponse($expected_status['edit'], SafeMarkup::format('The @user_label has the expected edit access.', $args));
$this->assertResponse($expected_status['edit'], new FormattableMarkup('The @user_label has the expected edit access.', $args));
// Check whether the user is allowed to access the entity delete form.
$delete_url = $this->entity->urlInfo('delete-form', $options);
$this->drupalGet($delete_url, $options);
$this->assertResponse($expected_status['delete'], SafeMarkup::format('The @user_label has the expected delete access.', $args));
$this->assertResponse($expected_status['delete'], new FormattableMarkup('The @user_label has the expected delete access.', $args));
// Check whether the user is allowed to access the translation overview.
$langcode = $this->langcodes[1];
$options['language'] = $languages[$langcode];
$translations_url = $this->entity->url('drupal:content-translation-overview', $options);
$this->drupalGet($translations_url);
$this->assertResponse($expected_status['overview'], SafeMarkup::format('The @user_label has the expected translation overview access.', $args));
$this->assertResponse($expected_status['overview'], new FormattableMarkup('The @user_label has the expected translation overview access.', $args));
// Check whether the user is allowed to create a translation.
$add_translation_url = Url::fromRoute("entity.$this->entityTypeId.content_translation_add", [$this->entityTypeId => $this->entity->id(), 'source' => $default_langcode, 'target' => $langcode], $options);
@@ -189,7 +189,7 @@ class ContentTranslationWorkflowsTest extends ContentTranslationTestBase {
else {
$this->drupalGet($add_translation_url);
}
$this->assertResponse($expected_status['add_translation'], SafeMarkup::format('The @user_label has the expected translation creation access.', $args));
$this->assertResponse($expected_status['add_translation'], new FormattableMarkup('The @user_label has the expected translation creation access.', $args));
// Check whether the user is allowed to edit a translation.
$langcode = $this->langcodes[2];
@@ -217,7 +217,7 @@ class ContentTranslationWorkflowsTest extends ContentTranslationTestBase {
else {
$this->drupalGet($edit_translation_url);
}
$this->assertResponse($expected_status['edit_translation'], SafeMarkup::format('The @user_label has the expected translation edit access.', $args));
$this->assertResponse($expected_status['edit_translation'], new FormattableMarkup('The @user_label has the expected translation edit access.', $args));
// Check whether the user is allowed to delete a translation.
$langcode = $this->langcodes[2];
@@ -245,7 +245,7 @@ class ContentTranslationWorkflowsTest extends ContentTranslationTestBase {
else {
$this->drupalGet($delete_translation_url);
}
$this->assertResponse($expected_status['delete_translation'], SafeMarkup::format('The @user_label has the expected translation deletion access.', $args));
$this->assertResponse($expected_status['delete_translation'], new FormattableMarkup('The @user_label has the expected translation deletion access.', $args));
}
/**
@@ -4,12 +4,13 @@ namespace Drupal\Tests\content_translation\Functional\Update;
use Drupal\Core\Language\LanguageInterface;
use Drupal\FunctionalTests\Update\UpdatePathTestBase;
use Drupal\system\Tests\Entity\EntityDefinitionTestTrait;
use Drupal\Tests\system\Functional\Entity\Traits\EntityDefinitionTestTrait;
/**
* Tests the upgrade path for the Content Translation module.
*
* @group Update
* @group legacy
*/
class ContentTranslationUpdateTest extends UpdatePathTestBase {
@@ -2,7 +2,7 @@
namespace Drupal\Tests\content_translation\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\JavascriptTestBase;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
use Drupal\language\Entity\ConfigurableLanguage;
/**
@@ -10,7 +10,7 @@ use Drupal\language\Entity\ConfigurableLanguage;
*
* @group content_translation
*/
class ContentTranslationContextualLinksTest extends JavascriptTestBase {
class ContentTranslationContextualLinksTest extends WebDriverTestBase {
/**
* The 'translator' user to use during testing.
@@ -33,6 +33,7 @@ class ContentTranslationConfigImportTest extends KernelTestBase {
protected function setUp() {
parent::setUp();
$this->installConfig(['system']);
$this->installEntitySchema('entity_test_mul');
$this->copyConfig($this->container->get('config.storage'), $this->container->get('config.storage.sync'));
@@ -74,7 +75,7 @@ class ContentTranslationConfigImportTest extends KernelTestBase {
'langcode' => 'en',
'status' => TRUE,
'dependencies' => [
'module' => ['content_translation']
'module' => ['content_translation'],
],
'id' => $config_id,
'target_entity_type_id' => 'entity_test_mul',
@@ -20,6 +20,8 @@ class MigrateTaxonomyTermTranslationTest extends MigrateDrupal6TestBase {
'content_translation',
'language',
'menu_ui',
// Required for translation migrations.
'migrate_drupal_multilingual',
'node',
'taxonomy',
];
@@ -78,7 +80,7 @@ class MigrateTaxonomyTermTranslationTest extends MigrateDrupal6TestBase {
$this->assertInstanceOf(TermInterface::class, $entity);
$this->assertSame($expected_language, $entity->language()->getId());
$this->assertSame($expected_label, $entity->label());
$this->assertSame($expected_vid, $entity->getVocabularyId());
$this->assertSame($expected_vid, $entity->bundle());
$this->assertSame($expected_description, $entity->getDescription());
$this->assertSame($expected_format, $entity->getFormat());
$this->assertSame($expected_weight, $entity->getWeight());
@@ -0,0 +1,99 @@
<?php
namespace Drupal\Tests\content_translation\Kernel\Migrate\d7;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Tests the migration of entity translation settings.
*
* @group migrate_drupal_7
*/
class MigrateEntityTranslationSettingsTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'comment',
'content_translation',
'language',
'menu_ui',
// Required for translation migrations.
'migrate_drupal_multilingual',
'node',
'taxonomy',
'text',
'user',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig([
'comment',
'content_translation',
'node',
'taxonomy',
'user',
]);
$this->installEntitySchema('comment');
$this->installEntitySchema('node');
$this->installEntitySchema('taxonomy_term');
$this->installEntitySchema('user');
$this->executeMigrations([
'd7_comment_type',
'd7_node_type',
'd7_taxonomy_vocabulary',
'd7_entity_translation_settings',
]);
}
/**
* Tests entity translation settings migration.
*/
public function testEntityTranslationSettingsMigration() {
// Tests 'comment_node_test_content_type' entity translation settings.
$config = $this->config('language.content_settings.comment.comment_node_test_content_type');
$this->assertSame($config->get('target_entity_type_id'), 'comment');
$this->assertSame($config->get('target_bundle'), 'comment_node_test_content_type');
$this->assertSame($config->get('default_langcode'), 'current_interface');
$this->assertFalse((bool) $config->get('language_alterable'));
$this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled'));
$this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide'));
// Tests 'test_content_type' entity translation settings.
$config = $this->config('language.content_settings.node.test_content_type');
$this->assertSame($config->get('target_entity_type_id'), 'node');
$this->assertSame($config->get('target_bundle'), 'test_content_type');
$this->assertSame($config->get('default_langcode'), LanguageInterface::LANGCODE_NOT_SPECIFIED);
$this->assertTrue((bool) $config->get('language_alterable'));
$this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled'));
$this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide'));
// Tests 'test_vocabulary' entity translation settings.
$config = $this->config('language.content_settings.taxonomy_term.test_vocabulary');
$this->assertSame($config->get('target_entity_type_id'), 'taxonomy_term');
$this->assertSame($config->get('target_bundle'), 'test_vocabulary');
$this->assertSame($config->get('default_langcode'), LanguageInterface::LANGCODE_SITE_DEFAULT);
$this->assertFalse((bool) $config->get('language_alterable'));
$this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled'));
$this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide'));
// Tests 'user' entity translation settings.
$config = $this->config('language.content_settings.user.user');
$this->assertSame($config->get('target_entity_type_id'), 'user');
$this->assertSame($config->get('target_bundle'), 'user');
$this->assertSame($config->get('default_langcode'), LanguageInterface::LANGCODE_SITE_DEFAULT);
$this->assertFalse((bool) $config->get('language_alterable'));
$this->assertTrue((bool) $config->get('third_party_settings.content_translation.enabled'));
$this->assertFalse((bool) $config->get('third_party_settings.content_translation.bundle_settings.untranslatable_fields_hide'));
}
}
@@ -0,0 +1,254 @@
<?php
namespace Drupal\Tests\content_translation\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests entity translation settings source plugin.
*
* @covers \Drupal\content_translation\Plugin\migrate\source\d7\EntityTranslationSettings
*
* @group content_translation
*/
class EntityTranslationSettingsTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'content_translation',
'language',
'migrate_drupal',
];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// Source data when there's no entity type that uses entity translation.
$tests[0]['source_data']['variable'] = [
[
'name' => 'entity_translation_entity_types',
'value' => 'a:4:{s:7:"comment";i:0;s:4:"node";i:0;s:13:"taxonomy_term";i:0;s:4:"user";i:0;}',
],
];
// Source data when there's no bundle settings variables.
$tests[1]['source_data']['variable'] = [
[
'name' => 'entity_translation_entity_types',
'value' => 'a:4:{s:7:"comment";s:7:"comment";s:4:"node";s:4:"node";s:13:"taxonomy_term";s:13:"taxonomy_term";s:4:"user";s:4:"user";}',
],
[
'name' => 'entity_translation_taxonomy',
'value' => 'a:3:{s:6:"forums";b:1;s:4:"tags";b:1;s:4:"test";b:0;}',
],
[
'name' => 'language_content_type_article',
'value' => 's:1:"2";',
],
[
'name' => 'language_content_type_forum',
'value' => 's:1:"4";',
],
[
'name' => 'language_content_type_page',
'value' => 's:1:"4";',
],
];
// Source data when there's bundle settings variables.
$tests[2]['source_data']['variable'] = [
[
'name' => 'entity_translation_entity_types',
'value' => 'a:4:{s:7:"comment";s:7:"comment";s:4:"node";s:4:"node";s:13:"taxonomy_term";s:13:"taxonomy_term";s:4:"user";s:4:"user";}',
],
[
'name' => 'entity_translation_settings_comment__comment_node_forum',
'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}',
],
[
'name' => 'entity_translation_settings_comment__comment_node_page',
'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:0;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}',
],
[
'name' => 'entity_translation_settings_node__forum',
'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:0;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}',
],
[
'name' => 'entity_translation_settings_node__page',
'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-default";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}',
],
[
'name' => 'entity_translation_settings_taxonomy_term__forums',
'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-current";s:22:"hide_language_selector";i:0;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}',
],
[
'name' => 'entity_translation_settings_taxonomy_term__tags',
'value' => 'a:5:{s:16:"default_language";s:13:"xx-et-current";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:0;}',
],
[
'name' => 'entity_translation_settings_user__user',
'value' => 'a:5:{s:16:"default_language";s:12:"xx-et-author";s:22:"hide_language_selector";i:1;s:21:"exclude_language_none";i:0;s:13:"lock_language";i:0;s:27:"shared_fields_original_only";i:1;}',
],
[
'name' => 'entity_translation_taxonomy',
'value' => 'a:3:{s:6:"forums";b:1;s:4:"tags";b:1;s:4:"test";b:0;}',
],
[
'name' => 'language_content_type_article',
'value' => 's:1:"2";',
],
[
'name' => 'language_content_type_forum',
'value' => 's:1:"4";',
],
[
'name' => 'language_content_type_page',
'value' => 's:1:"4";',
],
];
// Source data when taxonomy terms are translatable but the
// 'entity_translation_taxonomy' variable is not set.
$tests[3]['source_data']['variable'] = [
[
'name' => 'entity_translation_entity_types',
'value' => 'a:4:{s:7:"comment";i:0;s:4:"node";i:0;s:13:"taxonomy_term";i:1;s:4:"user";i:0;}',
],
];
// Expected data when there's no entity type that uses entity translation.
$tests[0]['expected_data'] = [];
// Expected data when there's no bundle settings variables.
$tests[1]['expected_data'] = [
[
'id' => 'node.forum',
'target_entity_type_id' => 'node',
'target_bundle' => 'forum',
'default_langcode' => 'und',
'language_alterable' => TRUE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'node.page',
'target_entity_type_id' => 'node',
'target_bundle' => 'page',
'default_langcode' => 'und',
'language_alterable' => TRUE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'comment.comment_forum',
'target_entity_type_id' => 'comment',
'target_bundle' => 'comment_forum',
'default_langcode' => 'xx-et-current',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'comment.comment_node_page',
'target_entity_type_id' => 'comment',
'target_bundle' => 'comment_node_page',
'default_langcode' => 'xx-et-current',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'taxonomy_term.forums',
'target_entity_type_id' => 'taxonomy_term',
'target_bundle' => 'forums',
'default_langcode' => 'xx-et-default',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'taxonomy_term.tags',
'target_entity_type_id' => 'taxonomy_term',
'target_bundle' => 'tags',
'default_langcode' => 'xx-et-default',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'user.user',
'target_entity_type_id' => 'user',
'target_bundle' => 'user',
'default_langcode' => 'xx-et-default',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => FALSE,
],
];
// Expected data when there's bundle settings variables.
$tests[2]['expected_data'] = [
[
'id' => 'node.forum',
'target_entity_type_id' => 'node',
'target_bundle' => 'forum',
'default_langcode' => 'xx-et-author',
'language_alterable' => TRUE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'node.page',
'target_entity_type_id' => 'node',
'target_bundle' => 'page',
'default_langcode' => 'xx-et-default',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => TRUE,
],
[
'id' => 'comment.comment_forum',
'target_entity_type_id' => 'comment',
'target_bundle' => 'comment_forum',
'default_langcode' => 'xx-et-author',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'comment.comment_node_page',
'target_entity_type_id' => 'comment',
'target_bundle' => 'comment_node_page',
'default_langcode' => 'xx-et-author',
'language_alterable' => TRUE,
'untranslatable_fields_hide' => TRUE,
],
[
'id' => 'taxonomy_term.forums',
'target_entity_type_id' => 'taxonomy_term',
'target_bundle' => 'forums',
'default_langcode' => 'xx-et-current',
'language_alterable' => TRUE,
'untranslatable_fields_hide' => TRUE,
],
[
'id' => 'taxonomy_term.tags',
'target_entity_type_id' => 'taxonomy_term',
'target_bundle' => 'tags',
'default_langcode' => 'xx-et-current',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => FALSE,
],
[
'id' => 'user.user',
'target_entity_type_id' => 'user',
'target_bundle' => 'user',
'default_langcode' => 'xx-et-author',
'language_alterable' => FALSE,
'untranslatable_fields_hide' => TRUE,
],
];
// Expected data when taxonomy terms are translatable but the
// 'entity_translation_taxonomy' variable is not set.
$tests[3]['expected_data'] = [];
return $tests;
}
}