diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 177a495..c2e5e76 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -154,10 +154,10 @@ public function __construct(array $values, $entity_type, $bundle = FALSE, $trans
// original language.
$data = array('status' => static::TRANSLATION_EXISTING);
$this->translations[Language::LANGCODE_DEFAULT] = $data;
+ $this->initializeDefaultLanguage();
if ($translations) {
- $default_langcode = $this->language()->id;
foreach ($translations as $langcode) {
- if ($langcode != $default_langcode && $langcode != Language::LANGCODE_DEFAULT) {
+ if ($langcode != $this->language->id && $langcode != Language::LANGCODE_DEFAULT) {
$this->translations[$langcode] = $data;
}
}
@@ -399,7 +399,8 @@ protected function getTranslatedField($property_name, $langcode) {
}
// Non-translatable fields are always stored with
// Language::LANGCODE_DEFAULT as key.
- if ($langcode != Language::LANGCODE_DEFAULT && empty($definition['translatable'])) {
+ $default = $langcode == Language::LANGCODE_DEFAULT;
+ if (!$default && empty($definition['translatable'])) {
if (!isset($this->fields[$property_name][Language::LANGCODE_DEFAULT])) {
$this->fields[$property_name][Language::LANGCODE_DEFAULT] = $this->getTranslatedField($property_name, Language::LANGCODE_DEFAULT);
}
@@ -411,7 +412,14 @@ protected function getTranslatedField($property_name, $langcode) {
$value = $this->values[$property_name][$langcode];
}
$field = \Drupal::typedData()->getPropertyInstance($this, $property_name, $value);
- $field->setLangcode($langcode);
+ if (!$default) {
+ $field->setLangcode($langcode);
+ }
+ // If we are initializing the default language cache, the variable is
+ // not populated, thus we have no valid value to set.
+ elseif (isset($this->language)) {
+ $field->setLangcode($this->language->id);
+ }
$this->fields[$property_name][$langcode] = $field;
}
}
@@ -531,17 +539,17 @@ public function language() {
return $this->languages[$this->activeLangcode];
}
else {
- return $this->language ?: $this->getDefaultLanguage();
+ return $this->language;
}
}
/**
- * Returns the entity original language.
+ * Initializes the entity original language local cache.
*
* @return \Drupal\Core\Language\Language
* A language object.
*/
- protected function getDefaultLanguage() {
+ protected function initializeDefaultLanguage() {
// Keep a local cache of the language object and clear it if the langcode
// gets changed, see ContentEntityBase::onChange().
if (!isset($this->language)) {
@@ -553,11 +561,32 @@ protected function getDefaultLanguage() {
// Make sure we return a proper language object.
$this->language = new Language(array('id' => Language::LANGCODE_NOT_SPECIFIED, 'locked' => TRUE));
}
+ // This needs to be initialized manually as it is skipped when
+ // instantiating the language field object to avoid infinite recursion.
+ if (!empty($this->fields['langcode'])) {
+ $this->fields['langcode'][Language::LANGCODE_DEFAULT]->setLangcode($this->language->id);
+ }
}
return $this->language;
}
/**
+ * Updates language for already instantiated fields.
+ *
+ * @return \Drupal\Core\Language\Language
+ * A language object.
+ */
+ protected function updateFieldLangcodes($langcode) {
+ if (!empty($this->fields)) {
+ foreach ($this->fields as $name => $items) {
+ if (!empty($items[Language::LANGCODE_DEFAULT])) {
+ $items[Language::LANGCODE_DEFAULT]->setLangcode($langcode);
+ }
+ }
+ }
+ }
+
+ /**
* {@inheritdoc}
*/
public function onChange($property_name) {
@@ -565,6 +594,8 @@ public function onChange($property_name) {
// Avoid using unset as this unnecessarily triggers magic methods later
// on.
$this->language = NULL;
+ $this->initializeDefaultLanguage();
+ $this->updateFieldLangcodes($this->language->id);
}
}
@@ -576,11 +607,8 @@ public function onChange($property_name) {
public function getTranslation($langcode) {
// Ensure we always use the default language code when dealing with the
// original entity language.
- if ($langcode != Language::LANGCODE_DEFAULT) {
- $default_language = $this->language ?: $this->getDefaultLanguage();
- if ($langcode == $default_language->id) {
- $langcode = Language::LANGCODE_DEFAULT;
- }
+ if ($langcode != Language::LANGCODE_DEFAULT && $langcode == $this->language->id) {
+ $langcode = Language::LANGCODE_DEFAULT;
}
// Populate entity translation object cache so it will be available for all
@@ -607,7 +635,7 @@ public function getTranslation($langcode) {
// If the entity or the requested language is not a configured
// language, we fall back to the entity itself, since in this case it
// cannot have translations.
- $translation = empty($this->getDefaultLanguage()->locked) && empty($languages[$langcode]->locked) ? $this->addTranslation($langcode) : $this;
+ $translation = empty($this->language->locked) && empty($languages[$langcode]->locked) ? $this->addTranslation($langcode) : $this;
}
}
}
@@ -667,8 +695,7 @@ protected function initializeTranslation($langcode) {
* {@inheritdoc}
*/
public function hasTranslation($langcode) {
- $default_language = $this->language ?: $this->getDefaultLanguage();
- if ($langcode == $default_language->id) {
+ if ($langcode == $this->language->id) {
$langcode = Language::LANGCODE_DEFAULT;
}
return !empty($this->translations[$langcode]['status']);
@@ -715,7 +742,7 @@ public function addTranslation($langcode, array $values = array()) {
* {@inheritdoc}
*/
public function removeTranslation($langcode) {
- if (isset($this->translations[$langcode]) && $langcode != Language::LANGCODE_DEFAULT && $langcode != $this->getDefaultLanguage()->id) {
+ if (isset($this->translations[$langcode]) && $langcode != Language::LANGCODE_DEFAULT && $langcode != $this->language->id) {
foreach ($this->getPropertyDefinitions() as $name => $definition) {
if (!empty($definition['translatable'])) {
unset($this->values[$name][$langcode]);
@@ -734,7 +761,7 @@ public function removeTranslation($langcode) {
* {@inheritdoc}
*/
public function initTranslation($langcode) {
- if ($langcode != Language::LANGCODE_DEFAULT && $langcode != $this->getDefaultLanguage()->id) {
+ if ($langcode != Language::LANGCODE_DEFAULT && $langcode != $this->language->id) {
$this->translations[$langcode]['status'] = static::TRANSLATION_EXISTING;
}
}
@@ -747,8 +774,7 @@ public function getTranslationLanguages($include_default = TRUE) {
unset($translations[Language::LANGCODE_DEFAULT]);
if ($include_default) {
- $langcode = $this->getDefaultLanguage()->id;
- $translations[$langcode] = TRUE;
+ $translations[$this->language->id] = TRUE;
}
// Now load language objects based upon translation langcodes.
@@ -908,10 +934,7 @@ public function __clone() {
// original reference and re-creating its values.
$this->clearTranslationCache();
$translations = $this->translations;
- unset($this->translations);
- // This will trigger the magic setter as the translations array is
- // undefined now.
- $this->translations = $translations;
+ $this->translations = &$translations;
}
}
diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
index 5497efb..353aab0 100644
--- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
+++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php
@@ -325,7 +325,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
// Get the revision IDs.
$revision_ids = array();
foreach ($entities as $values) {
- $revision_ids[] = $values[$this->revisionKey];
+ $revision_ids[] = $values[$this->revisionKey][Language::LANGCODE_DEFAULT];
}
$query->condition($this->revisionKey, $revision_ids);
}
@@ -849,41 +849,47 @@ protected function doLoadFieldItems($entities, $age) {
}
// Load field data.
- $all_langcodes = array_keys(language_list());
+ $all_langcodes = array_keys(language_list(Language::STATE_ALL));
foreach ($fields as $field_name => $field) {
$table = $load_current ? static::_fieldTableName($field) : static::_fieldRevisionTableName($field);
- // If the field is translatable ensure that only values having valid
- // languages are retrieved. Since we are loading values for multiple
- // entities, we cannot limit the query to the available translations.
- $langcodes = $field->isFieldTranslatable() ? $all_langcodes : array(Language::LANGCODE_NOT_SPECIFIED);
+ // Ensure that only values having valid languages are retrieved. Since we
+ // are loading values for multiple entities, we cannot limit the query to
+ // the available translations.
$results = $this->database->select($table, 't')
->fields('t')
->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN')
->condition('deleted', 0)
- ->condition('langcode', $langcodes, 'IN')
+ ->condition('langcode', $all_langcodes, 'IN')
->orderBy('delta')
->execute();
+ $translatable = $field->isFieldTranslatable();
$delta_count = array();
foreach ($results as $row) {
- if (!isset($delta_count[$row->entity_id][$row->langcode])) {
- $delta_count[$row->entity_id][$row->langcode] = 0;
- }
-
- if ($field->getFieldCardinality() == FieldInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getFieldCardinality()) {
- $item = array();
- // For each column declared by the field, populate the item from the
- // prefixed database column.
- foreach ($field->getColumns() as $column => $attributes) {
- $column_name = static::_fieldColumnName($field, $column);
- // Unserialize the value if specified in the column schema.
- $item[$column] = (!empty($attributes['serialize'])) ? unserialize($row->$column_name) : $row->$column_name;
+ // Ensure that records for non-translatable fields having invalid
+ // languages are skipped.
+ // @todo Remove BC support for 'und' untransltable fields as soon as can
+ // write a migration for them.
+ if ($translatable || $row->langcode == Language::LANGCODE_NOT_SPECIFIED || $row->langcode == $entities[$row->entity_id]->getUntranslated()->language()->id) {
+ if (!isset($delta_count[$row->entity_id][$row->langcode])) {
+ $delta_count[$row->entity_id][$row->langcode] = 0;
}
- // Add the item to the field values for the entity.
- $entities[$row->entity_id]->getTranslation($row->langcode)->{$field_name}[$delta_count[$row->entity_id][$row->langcode]] = $item;
- $delta_count[$row->entity_id][$row->langcode]++;
+ if ($field->getFieldCardinality() == FieldInterface::CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->langcode] < $field->getFieldCardinality()) {
+ $item = array();
+ // For each column declared by the field, populate the item from the
+ // prefixed database column.
+ foreach ($field->getColumns() as $column => $attributes) {
+ $column_name = static::_fieldColumnName($field, $column);
+ // Unserialize the value if specified in the column schema.
+ $item[$column] = (!empty($attributes['serialize'])) ? unserialize($row->$column_name) : $row->$column_name;
+ }
+
+ // Add the item to the field values for the entity.
+ $entities[$row->entity_id]->getTranslation($row->langcode)->{$field_name}[$delta_count[$row->entity_id][$row->langcode]] = $item;
+ $delta_count[$row->entity_id][$row->langcode]++;
+ }
}
}
}
@@ -897,6 +903,9 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
$id = $entity->id();
$bundle = $entity->bundle();
$entity_type = $entity->entityType();
+ $default_langcode = $entity->getUntranslated()->language()->id;
+ $translation_langcodes = array_keys($entity->getTranslationLanguages());
+
if (!isset($vid)) {
$vid = $id;
}
@@ -930,7 +939,7 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
$query = $this->database->insert($table_name)->fields($columns);
$revision_query = $this->database->insert($revision_name)->fields($columns);
- $langcodes = $field->isFieldTranslatable() ? array_keys($entity->getTranslationLanguages()) : array(Language::LANGCODE_NOT_SPECIFIED);
+ $langcodes = $field->isFieldTranslatable() ? $translation_langcodes : array($default_langcode);
foreach ($langcodes as $langcode) {
$delta_count = 0;
$items = $entity->getTranslation($langcode)->get($field_name);
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 00dcaba..da50ce1 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -39,7 +39,7 @@ class FieldItemList extends ItemList implements FieldItemListInterface {
*
* @var string
*/
- protected $langcode = Language::LANGCODE_DEFAULT;
+ protected $langcode = Language::LANGCODE_NOT_SPECIFIED;
/**
* Overrides TypedData::__construct().
diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php
index 7181b32..2f2dc54 100644
--- a/core/lib/Drupal/Core/Language/Language.php
+++ b/core/lib/Drupal/Core/Language/Language.php
@@ -59,11 +59,8 @@ class Language {
/**
* Language code referring to the default language of data, e.g. of an entity.
- *
- * @todo: Change value to differ from Language::LANGCODE_NOT_SPECIFIED once
- * field API leverages the property API.
*/
- const LANGCODE_DEFAULT = 'und';
+ const LANGCODE_DEFAULT = 'xx-default';
/**
* The language state when referring to configurable languages.
diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc
index 6d02b9d..4c767f0 100644
--- a/core/modules/content_translation/content_translation.admin.inc
+++ b/core/modules/content_translation/content_translation.admin.inc
@@ -331,9 +331,6 @@ function content_translation_form_language_content_settings_submit(array $form,
* language_save_default_configuration().
* - fields: An associative array with field names as keys and a boolean as
* value, indicating field translatability.
- *
- * @todo Remove this migration entirely once the Field API is converted to the
- * Entity Field API.
*/
function _content_translation_update_field_translatability($settings) {
$fields = array();
@@ -346,224 +343,15 @@ function _content_translation_update_field_translatability($settings) {
foreach ($bundle_settings['fields'] as $field_name => $translatable) {
// If a field is enabled for translation for at least one instance we
// need to mark it as translatable.
- if (FieldService::fieldInfo()->getField($entity_type, $field_name)) {
- $fields[$entity_type][$field_name] = $translatable || !empty($fields[$entity_type][$field_name]);
+ $field = FieldService::fieldInfo()->getField($entity_type, $field_name);
+ if ($field && $field->isFieldTranslatable() !== $translatable) {
+ $field->translatable = $translatable;
+ $field->save();
}
}
}
}
}
- $operations = array();
- foreach ($fields as $entity_type => $entity_type_fields) {
- foreach ($entity_type_fields as $field_name => $translatable) {
- $field = field_info_field($entity_type, $field_name);
- if ($field->isFieldTranslatable() != $translatable) {
- // If a field is untranslatable, it can have no data except under
- // Language::LANGCODE_NOT_SPECIFIED. Thus we need a field to be translatable before
- // we convert data to the entity language. Conversely we need to switch
- // data back to Language::LANGCODE_NOT_SPECIFIED before making a field
- // untranslatable lest we lose information.
- $field_operations = array(
- array('content_translation_translatable_switch', array($translatable, $entity_type, $field_name)),
- );
- if ($field->hasData()) {
- $field_operations[] = array('content_translation_translatable_batch', array($translatable, $field_name));
- $field_operations = $translatable ? $field_operations : array_reverse($field_operations);
- }
- $operations = array_merge($operations, $field_operations);
- }
- }
- }
-
- // As last operation store the submitted settings.
- $operations[] = array('content_translation_save_settings', array($settings));
-
- $batch = array(
- 'title' => t('Updating translatability for the selected fields'),
- 'operations' => $operations,
- 'finished' => 'content_translation_translatable_batch_done',
- 'file' => drupal_get_path('module', 'content_translation') . '/content_translation.admin.inc',
- );
- batch_set($batch);
-}
-
-/**
- * Toggles translatability of the given field.
- *
- * This is called from a batch operation, but should only run once per field.
- *
- * @param bool $translatable
- * Indicator of whether the field should be made translatable (TRUE) or
- * untranslatble (FALSE).
- * @param string $entity_type
- * Field entity type.
- * @param string $field_name
- * Field machine name.
- */
-function content_translation_translatable_switch($translatable, $entity_type, $field_name) {
- $field = field_info_field($entity_type, $field_name);
- if ($field->isFieldTranslatable() !== $translatable) {
- $field->translatable = $translatable;
- $field->save();
- }
+ content_translation_save_settings($settings);
}
-
-/**
- * Batch callback: Converts field data to or from Language::LANGCODE_NOT_SPECIFIED.
- *
- * @param bool $translatable
- * Indicator of whether the field should be made translatable (TRUE) or
- * untranslatble (FALSE).
- * @param string $field_name
- * Field machine name.
- */
-function content_translation_translatable_batch($translatable, $field_name, &$context) {
- // Determine the entity types to act on.
- $entity_types = array();
- foreach (field_info_instances() as $entity_type => $info) {
- foreach ($info as $bundle => $instances) {
- foreach ($instances as $instance_field_name => $instance) {
- if ($instance_field_name == $field_name) {
- $entity_types[] = $entity_type;
- break 2;
- }
- }
- }
- }
-
- if (empty($context['sandbox'])) {
- $context['sandbox']['progress'] = 0;
- $context['sandbox']['max'] = 0;
-
- foreach ($entity_types as $entity_type) {
- $field = field_info_field($entity_type, $field_name);
- $columns = $field->getColumns();
- $column = isset($columns['value']) ? 'value' : key($columns);
- $query_field = "$field_name.$column";
-
- // How many entities will need processing?
- $query = \Drupal::entityQuery($entity_type);
- $count = $query
- ->exists($query_field)
- ->count()
- ->execute();
-
- $context['sandbox']['max'] += $count;
- $context['sandbox']['progress_entity_type'][$entity_type] = 0;
- $context['sandbox']['max_entity_type'][$entity_type] = $count;
- }
-
- if ($context['sandbox']['max'] === 0) {
- // Nothing to do.
- $context['finished'] = 1;
- return;
- }
- }
-
- foreach ($entity_types as $entity_type) {
- if ($context['sandbox']['max_entity_type'][$entity_type] === 0) {
- continue;
- }
-
- $info = entity_get_info($entity_type);
- $offset = $context['sandbox']['progress_entity_type'][$entity_type];
- $query = \Drupal::entityQuery($entity_type);
- $field = field_info_field($entity_type, $field_name);
- $columns = $field->getColumns();
- $column = isset($columns['value']) ? 'value' : key($columns);
- $query_field = "$field_name.$column";
- $result = $query
- ->exists($query_field)
- ->sort($info['entity_keys']['id'])
- ->range($offset, 10)
- ->execute();
-
- foreach (entity_load_multiple($entity_type, $result) as $id => $entity) {
- $context['sandbox']['max_entity_type'][$entity_type] -= count($result);
- $context['sandbox']['progress_entity_type'][$entity_type]++;
- $context['sandbox']['progress']++;
- $langcode = $entity->language()->id;
-
- // Skip process for language neutral entities.
- if ($langcode == Language::LANGCODE_NOT_SPECIFIED) {
- continue;
- }
-
- // We need a two-step approach while updating field translations: given
- // that field-specific update functions might rely on the stored values to
- // perform their processing first we need to store the new translations
- // and only after we can remove the old ones. Otherwise we might have data
- // loss, since the removal of the old translations might occur before the
- // new ones are stored.
- if ($translatable && isset($entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED])) {
- // If the field is being switched to translatable and has data for
- // Language::LANGCODE_NOT_SPECIFIED then we need to move the data to the right
- // language.
- $entity->{$field_name}[$langcode] = $entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED];
- // Store the original value.
- _content_translation_update_field($entity_type, $entity, $field_name);
- $entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED] = array();
- // Remove the language neutral value.
- _content_translation_update_field($entity_type, $entity, $field_name);
- }
- elseif (!$translatable && isset($entity->{$field_name}[$langcode])) {
- // The field has been marked untranslatable and has data in the entity
- // language: we need to move it to Language::LANGCODE_NOT_SPECIFIED and drop the
- // other translations.
- $entity->{$field_name}[Language::LANGCODE_NOT_SPECIFIED] = $entity->{$field_name}[$langcode];
- // Store the original value.
- _content_translation_update_field($entity_type, $entity, $field_name);
- // Remove translations.
- foreach ($entity->{$field_name} as $langcode => $items) {
- if ($langcode != Language::LANGCODE_NOT_SPECIFIED) {
- $entity->{$field_name}[$langcode] = array();
- }
- }
- _content_translation_update_field($entity_type, $entity, $field_name);
- }
- else {
- // No need to save unchanged entities.
- continue;
- }
- }
- }
-
- $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
-}
-
-/**
- * Stores the given field translations.
- */
-function _content_translation_update_field($entity_type, EntityInterface $entity, $field_name) {
- $empty = 0;
- $translations = $entity->getTranslationLanguages();
-
- // Ensure that we are trying to store only valid data.
- foreach (array_keys($translations) as $langcode) {
- $items = $entity->getTranslation($langcode)->get($field_name);
- $items->filterEmptyValues();
- $empty += $items->isEmpty();
- }
-
- // Save the field value only if there is at least one item available,
- // otherwise any stored empty field value would be deleted. If this happens
- // the range queries would be messed up.
- if ($empty < count($translations)) {
- $entity->save();
- }
-}
-
-/**
- * Batch finished callback: Checks the exit status of the batch operation.
- */
-function content_translation_translatable_batch_done($success, $results, $operations) {
- if ($success) {
- drupal_set_message(t("Successfully changed field translation setting."));
- }
- else {
- // @todo: Do something about this case.
- drupal_set_message(t("Something went wrong while processing data. Some nodes may appear to have lost fields."), 'error');
- }
-}
-
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index b31b8d8..48639c8 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -217,12 +217,6 @@ function content_translation_menu() {
}
}
- $items['admin/config/regional/content_translation/translatable/%/%'] = array(
- 'title' => 'Confirm change in translatability.',
- 'description' => 'Confirm page for changing field translatability.',
- 'route_name' => 'content_translation.translatable',
- );
-
return $items;
}
@@ -815,36 +809,12 @@ function content_translation_field_extra_fields() {
* Implements hook_form_FORM_ID_alter() for 'field_ui_field_edit_form'.
*/
function content_translation_form_field_ui_field_edit_form_alter(array &$form, array &$form_state, $form_id) {
- $field = $form['#field'];
- $field_name = $field->getFieldName();
- $translatable = $field->isFieldTranslatable();
- $entity_type = $field->entity_type;
- $label = t('Field translation');
-
- if ($field->hasData()) {
- $form['field']['translatable'] = array(
- '#type' => 'item',
- '#title' => $label,
- '#attributes' => array('class' => 'translatable'),
- 'link' => array(
- '#type' => 'link',
- '#prefix' => t('This field has data in existing content.') . ' ',
- '#title' => !$translatable ? t('Enable translation') : t('Disable translation'),
- '#href' => "admin/config/regional/content_translation/translatable/$entity_type/$field_name",
- '#options' => array('query' => drupal_get_destination()),
- '#access' => user_access('administer content translation'),
- ),
- );
- }
- else {
- $form['field']['translatable'] = array(
- '#type' => 'checkbox',
- '#title' => t('Users may translate this field.'),
- '#default_value' => $translatable,
- );
- }
-
- $form['field']['translatable']['#weight'] = 20;
+ $form['field']['translatable'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Users may translate this field.'),
+ '#default_value' => $form['#field']->isFieldTranslatable(),
+ '#weight' => 20,
+ );
}
/**
diff --git a/core/modules/content_translation/content_translation.routing.yml b/core/modules/content_translation/content_translation.routing.yml
deleted file mode 100644
index 51db4a3..0000000
--- a/core/modules/content_translation/content_translation.routing.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-content_translation.translatable:
- path: '/admin/config/regional/content_translation/translatable/{entity_type}/{field_name}'
- defaults:
- _form: 'Drupal\content_translation\Form\TranslatableForm'
- requirements:
- _permission: 'administer content translation'
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Form/TranslatableForm.php b/core/modules/content_translation/lib/Drupal/content_translation/Form/TranslatableForm.php
deleted file mode 100644
index 363cb1c..0000000
--- a/core/modules/content_translation/lib/Drupal/content_translation/Form/TranslatableForm.php
+++ /dev/null
@@ -1,156 +0,0 @@
-field->isFieldTranslatable()) {
- $question = t('Are you sure you want to disable translation for the %name field?', array('%name' => $this->fieldName));
- }
- else {
- $question = t('Are you sure you want to enable translation for the %name field?', array('%name' => $this->fieldName));
- }
- return $question;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getDescription() {
- $description = t('By submitting this form these changes will apply to the %name field everywhere it is used.',
- array('%name' => $this->fieldName)
- );
- $description .= $this->field->isFieldTranslatable() ? "
" . t("All the existing translations of this field will be deleted.
This action cannot be undone.") : '';
- return $description;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getCancelRoute() {
- return array(
- 'route_name' => '',
- );
- }
-
- /**
- * {@inheritdoc}
- * @param string $entity_type
- * The entity type.
- * @param string $field_name
- * The field name.
- */
- public function buildForm(array $form, array &$form_state, $entity_type = NULL, $field_name = NULL) {
- $this->fieldName = $field_name;
- $this->fieldInfo = FieldInfo::fieldInfo()->getField($entity_type, $field_name);
-
- return parent::buildForm($form, $form_state);
- }
-
- /**
- * Form submission handler.
- *
- * This submit handler maintains consistency between the translatability of an
- * entity and the language under which the field data is stored. When a field
- * is marked as translatable, all the data in
- * $entity->{field_name}[Language::LANGCODE_NOT_SPECIFIED] is moved to
- * $entity->{field_name}[$entity_language]. When a field is marked as
- * untranslatable the opposite process occurs. Note that marking a field as
- * untranslatable will cause all of its translations to be permanently
- * removed, with the exception of the one corresponding to the entity
- * language.
- *
- * @param array $form
- * An associative array containing the structure of the form.
- * @param array $form_state
- * An associative array containing the current state of the form.
- */
- public function submitForm(array &$form, array &$form_state) {
- // This is the current state that we want to reverse.
- $translatable = $form_state['values']['translatable'];
- if ($this->field->translatable !== $translatable) {
- // Field translatability has changed since form creation, abort.
- $t_args = array('%field_name');
- $msg = $translatable ?
- t('The field %field_name is already translatable. No change was performed.', $t_args):
- t('The field %field_name is already untranslatable. No change was performed.', $t_args);
- drupal_set_message($msg, 'warning');
- return;
- }
-
- // If a field is untranslatable, it can have no data except under
- // Language::LANGCODE_NOT_SPECIFIED. Thus we need a field to be translatable
- // before we convert data to the entity language. Conversely we need to
- // switch data back to Language::LANGCODE_NOT_SPECIFIED before making a
- // field untranslatable lest we lose information.
- $operations = array(
- array(
- 'content_translation_translatable_batch', array(
- !$translatable,
- $this->fieldName,
- ),
- ),
- array(
- 'content_translation_translatable_switch', array(
- !$translatable,
- $this->field['entity_type'],
- $this->fieldName,
- ),
- ),
- );
- $operations = $translatable ? $operations : array_reverse($operations);
-
- $t_args = array('%field' => $this->fieldName);
- $title = !$translatable ? t('Enabling translation for the %field field', $t_args) : t('Disabling translation for the %field field', $t_args);
-
- $batch = array(
- 'title' => $title,
- 'operations' => $operations,
- 'finished' => 'content_translation_translatable_batch_done',
- 'file' => drupal_get_path('module', 'content_translation') . '/content_translation.admin.inc',
- );
-
- batch_set($batch);
-
- }
-
-}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
index e2b0d4f..1f82ea9 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -118,7 +118,7 @@ protected function _testEntityLanguageMethods($entity_type) {
// Get the value.
$field = $entity->getTranslation(Language::LANGCODE_DEFAULT)->get($this->field_name);
$this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
- $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($field->getLangcode(), Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Set the value in a certain language. As the entity is not
// language-specific it should use the default language and so ignore the
@@ -131,11 +131,12 @@ protected function _testEntityLanguageMethods($entity_type) {
// language-specific entity.
$field = $entity->getTranslation($this->langcodes[1])->get($this->field_name);
$this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
- $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($field->getLangcode(), Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Now, make the entity language-specific by assigning a language and test
// translating it.
- $entity->langcode->value = $this->langcodes[0];
+ $default_langcode = $this->langcodes[0];
+ $entity->langcode->value = $default_langcode;
$entity->{$this->field_name} = array();
$this->assertEqual($entity->language(), language_load($this->langcodes[0]), format_string('%entity_type: Entity language retrieved.', array('%entity_type' => $entity_type)));
$this->assertFalse($entity->getTranslationLanguages(FALSE), format_string('%entity_type: No translations are available', array('%entity_type' => $entity_type)));
@@ -145,7 +146,7 @@ protected function _testEntityLanguageMethods($entity_type) {
// Get the value.
$field = $entity->get($this->field_name);
$this->assertEqual($field->value, 'default value', format_string('%entity_type: Untranslated value retrieved.', array('%entity_type' => $entity_type)));
- $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($field->getLangcode(), $default_langcode, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
// Set a translation.
$entity->getTranslation($this->langcodes[1])->set($this->field_name, array(0 => array('value' => 'translation 1')));
@@ -156,7 +157,7 @@ protected function _testEntityLanguageMethods($entity_type) {
// Make sure the untranslated value stays.
$field = $entity->get($this->field_name);
$this->assertEqual($field->value, 'default value', 'Untranslated value stays.');
- $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, 'Untranslated value has the expected langcode.');
+ $this->assertEqual($field->getLangcode(), $default_langcode, 'Untranslated value has the expected langcode.');
$translations[$this->langcodes[1]] = language_load($this->langcodes[1]);
$this->assertEqual($entity->getTranslationLanguages(FALSE), $translations, 'Translations retrieved.');
@@ -188,7 +189,7 @@ protected function _testEntityLanguageMethods($entity_type) {
// Get the value.
$field = $entity->get($field_name);
$this->assertEqual($field->value, 'default value2', format_string('%entity_type: Untranslated value set into a translation in non-strict mode.', array('%entity_type' => $entity_type)));
- $this->assertEqual($field->getLangcode(), Language::LANGCODE_DEFAULT, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($field->getLangcode(), $default_langcode, format_string('%entity_type: Field object has the expected langcode.', array('%entity_type' => $entity_type)));
}
/**
@@ -217,20 +218,19 @@ protected function _testMultilingualProperties($entity_type) {
$entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid));
$entity->save();
$entity = entity_load($entity_type, $entity->id());
- $this->assertEqual($entity->language()->id, Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Entity created as language neutral.', array('%entity_type' => $entity_type)));
+ $default_langcode = $entity->language()->id;
+ $this->assertEqual($default_langcode, Language::LANGCODE_NOT_SPECIFIED, format_string('%entity_type: Entity created as language neutral.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation(Language::LANGCODE_DEFAULT)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
- $this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation(Language::LANGCODE_DEFAULT)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as language neutral.', array('%entity_type' => $entity_type)));
- // As fields, translatable properties should ignore the given langcode and
- // use neutral language if the entity is not translatable.
$field = $entity->getTranslation($langcode)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to neutral language.', array('%entity_type' => $entity_type)));
- $this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to neutral language.', array('%entity_type' => $entity_type)));
$field = $entity->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
- $this->assertEqual(Language::LANGCODE_DEFAULT, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
// Create a language-aware entity and check that properties are stored
@@ -238,20 +238,21 @@ protected function _testMultilingualProperties($entity_type) {
$entity = entity_create($entity_type, array('name' => $name, 'user_id' => $uid, 'langcode' => $langcode));
$entity->save();
$entity = entity_load($entity_type, $entity->id());
- $this->assertEqual($entity->language()->id, $langcode, format_string('%entity_type: Entity created as language specific.', array('%entity_type' => $entity_type)));
+ $default_langcode = $entity->language()->id;
+ $this->assertEqual($default_langcode, $langcode, format_string('%entity_type: Entity created as language specific.', array('%entity_type' => $entity_type)));
$field = $entity->getTranslation($langcode)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
- $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored as a language-aware property.', array('%entity_type' => $entity_type)));
// Translatable properties on a translatable entity should use default
// language if Language::LANGCODE_NOT_SPECIFIED is passed.
$field = $entity->getTranslation(Language::LANGCODE_NOT_SPECIFIED)->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name defaults to the default language.', array('%entity_type' => $entity_type)));
- $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->getTranslation(Language::LANGCODE_NOT_SPECIFIED)->get('user_id')->target_id, format_string('%entity_type: The entity author defaults to the default language.', array('%entity_type' => $entity_type)));
$field = $entity->get('name');
$this->assertEqual($name, $field->value, format_string('%entity_type: The entity name can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
- $this->assertEqual(Language::LANGCODE_NOT_SPECIFIED, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
+ $this->assertEqual($default_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expect langcode.', array('%entity_type' => $entity_type)));
$this->assertEqual($uid, $entity->get('user_id')->target_id, format_string('%entity_type: The entity author can be retrieved without specifying a language.', array('%entity_type' => $entity_type)));
// Create property translations.
@@ -283,8 +284,7 @@ protected function _testMultilingualProperties($entity_type) {
);
$field = $entity->getTranslation($langcode)->get('name');
$this->assertEqual($properties[$langcode]['name'][0], $field->value, format_string('%entity_type: The entity name has been correctly stored for language %langcode.', $args));
- // Fields for the default entity langcode are seen as language neutral.
- $field_langcode = ($langcode == $entity->language()->id) ? Language::LANGCODE_NOT_SPECIFIED : $langcode;
+ $field_langcode = ($langcode == $entity->language()->id) ? $default_langcode : $langcode;
$this->assertEqual($field_langcode, $field->getLangcode(), format_string('%entity_type: The field object has the expected langcode %langcode.', $args));
$this->assertEqual($properties[$langcode]['user_id'][0], $entity->getTranslation($langcode)->get('user_id')->target_id, format_string('%entity_type: The entity author has been correctly stored for language %langcode.', $args));
}
@@ -480,6 +480,9 @@ function testEntityTranslationAPI() {
$cloned = clone $entity;
$translation = $cloned->getTranslation($langcode);
$this->assertNotIdentical($entity, $translation->getUntranslated(), 'A cloned entity object has no reference to the original one.');
+ $entity->removeTranslation($langcode);
+ $this->assertFalse($entity->hasTranslation($langcode));
+ $this->assertTrue($cloned->hasTranslation($langcode));
// Check that per-language defaults are properly populated.
$entity = $this->reloadEntity($entity);
diff --git a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
index 0b47055..49d9f78 100644
--- a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
+++ b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php
@@ -128,7 +128,7 @@ function testProcessedCache() {
$entity = entity_load($entity_type, $entity->id());
$cache = cache('field')->get("field:$entity_type:" . $entity->id());
$this->assertEqual($cache->data, array(
- Language::LANGCODE_DEFAULT => array(
+ Language::LANGCODE_NOT_SPECIFIED => array(
'summary_field' => array(
0 => array(
'value' => $value,
@@ -144,7 +144,7 @@ function testProcessedCache() {
// Inject fake processed values into the cache to make sure that these are
// used as-is and not re-calculated when the entity is loaded.
$data = array(
- Language::LANGCODE_DEFAULT => array(
+ Language::LANGCODE_NOT_SPECIFIED => array(
'summary_field' => array(
0 => array(
'value' => $value,