diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc index 6d02b9d..7bd994c 100644 --- a/core/modules/content_translation/content_translation.admin.inc +++ b/core/modules/content_translation/content_translation.admin.inc @@ -87,6 +87,8 @@ function _content_translation_form_language_content_settings_form_alter(array &$ // entity might have fields and if there are fields to translate. if (!empty($entity_info['fieldable'])) { $fields = $entity_manager->getFieldDefinitions($entity_type, $bundle); + $translation_metadata = content_translation_entity_field_info($entity_type); + if ($fields) { $form['settings'][$entity_type][$bundle]['translatable'] = array( '#type' => 'checkbox', @@ -121,8 +123,9 @@ function _content_translation_form_language_content_settings_form_alter(array &$ // Instead we need to rely on field definitions to determine whether // fields support translation. Whether they are actually enabled is // determined through our settings. As a consequence only fields - // that support translation can be enabled or disabled. - elseif (isset($field_settings[$field_name]) || !empty($definition['translatable'])) { + // that support translation can be enabled or disabled. We skip + // our own fields as they are always translatable. + elseif (isset($field_settings[$field_name]) || (!empty($definition['translatable']) && !isset($translation_metadata['definitions'][$field_name]))) { $form['settings'][$entity_type][$bundle]['fields'][$field_name] = array( '#label' => $definition['label'], '#type' => 'checkbox', diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 02e395e..b96a1f6 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -164,12 +164,14 @@ function content_translation_entity_field_info($entity_type) { 'label' => t('Translation source'), 'description' => t('The source language from which this translation was created.'), 'type' => 'field_item:language', + 'translatable' => TRUE, ); $info['definitions']['translation_outdated'] = array( 'label' => t('Translation outdated'), 'description' => t('A boolean indicating whether this translation needs to be updated.'), 'type' => 'field_item:boolean', + 'translatable' => TRUE, ); $info['definitions']['translation_uid'] = array( @@ -180,6 +182,7 @@ function content_translation_entity_field_info($entity_type) { 'target_type' => 'user', 'default_value' => 0, ), + 'translatable' => TRUE, ); $info['definitions']['translation_status'] = array( @@ -189,12 +192,14 @@ function content_translation_entity_field_info($entity_type) { 'settings' => array( 'default_value' => 1, ), + 'translatable' => TRUE, ); $info['definitions']['translation_created'] = array( 'label' => t('Translation created time'), 'description' => t('The Unix timestamp when the translation was created.'), 'type' => 'field_item:integer', + 'translatable' => TRUE, ); $info['definitions']['translation_changed'] = array( @@ -204,6 +209,7 @@ function content_translation_entity_field_info($entity_type) { 'property_constraints' => array( 'value' => array('EntityChanged' => array()), ), + 'translatable' => TRUE, ); return $info; @@ -756,14 +762,17 @@ function content_translation_load_translation_metadata(array $entities, $entity_ foreach ($result as $record) { $entity = $entities[$record->entity_id]; + foreach ($record as $key => $value) { if (!in_array($key, $exclude)) { $langcode = $record->langcode; if (!$entity->hasTranslation($langcode)) { $entity->initTranslation($langcode); } + $name = 'translation_' . $key; $item = $entity->getTranslation($langcode)->get($name); + if ($key != 'uid') { $item->value = $value; } @@ -784,24 +793,28 @@ function content_translation_entity_insert(EntityInterface $entity) { return; } + $definitions = $entity->getPropertyDefinitions(); $fields = array('entity_type', 'entity_id', 'langcode', 'source', 'outdated', 'uid', 'status', 'created', 'changed'); $query = db_insert('content_translation')->fields($fields); foreach ($entity->getTranslationLanguages() as $langcode => $language) { $translation = $entity->getTranslation($langcode); - $definitions = $entity->getPropertyDefinitions(); - $values = array(); + $record = array(); foreach ($fields as $key) { $name = 'translation_' . $key; if (isset($definitions[$name])) { $item = $translation->get($name); - $values[$key] = $key != 'uid' ? $item->value : $item->target_id; + $value = $key != 'uid' ? $item->value : $item->target_id; + if (isset($value)) { + $record[$key] = $value; + } } } - $values += array( - 'source' => '', + // FIXME Use field defaults instead. + $record += array( + 'source' => Language::LANGCODE_NOT_SPECIFIED, 'uid' => $GLOBALS['user']->id(), 'outdated' => FALSE, 'status' => TRUE, @@ -809,16 +822,16 @@ function content_translation_entity_insert(EntityInterface $entity) { 'changed' => REQUEST_TIME, ); - $values['entity_type'] = $entity->entityType(); - $values['entity_id'] = $entity->id(); - $values['langcode'] = $langcode; + $record['entity_type'] = $entity->entityType(); + $record['entity_id'] = $entity->id(); + $record['langcode'] = $langcode; // Reorder values to match the schema. - $record = array(); + $values = array(); foreach ($fields as $key) { - $record[$key] = is_bool($values[$name]) ? intval($values[$name]) : $values[$name]; + $values[$key] = is_bool($record[$key]) ? intval($record[$key]) : $record[$key]; } - $query->values($record); + $query->values($values); } $query->execute(); @@ -939,11 +952,16 @@ function content_translation_field_info_alter(&$info) { * Implements hook_entity_presave(). */ function content_translation_entity_presave(EntityInterface $entity) { - if ($entity instanceof ContentEntityInterface && $entity->isTranslatable()) { - // @todo Avoid using request attributes once translation metadata become - // regular fields. - $attributes = \Drupal::request()->attributes; - \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->id, $attributes->get('source_langcode')); + if ($entity instanceof ContentEntityInterface && $entity->isTranslatable() && !$entity->isNew()) { + // If we are creating a new translation we need to use the source language + // as original language, since source values are the only ones available to + // compare against. + if (!isset($entity->original)) { + $entity->original = entity_load_unchanged($entity->entityType(), $entity->id()); + } + $langcode = $entity->language()->id; + $source_langcode = !$entity->original->hasTranslation($langcode) ? $entity->translation_source->id : NULL; + \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $langcode, $source_langcode); } } diff --git a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php index ec4ad21..7991fe6 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php @@ -255,7 +255,12 @@ public function entityFormAlter(array &$form, array &$form_state, EntityInterfac ); } - $name = $new_translation ? $GLOBALS['user']->getUsername() : $entity->translation_uid->entity->getUsername(); + if ($new_translation) { + $name = $GLOBALS['user']->getUsername(); + } + else { + $name = $entity->translation_uid->value ? $entity->translation_uid->entity->getUsername() : ''; + } $form['content_translation']['name'] = array( '#type' => 'textfield', '#title' => t('Authored by'), @@ -403,13 +408,6 @@ public function entityFormEntityBuild($entity_type, EntityInterface $entity, arr if (!empty($values['retranslate'])) { $this->retranslate($entity, $form_langcode); } - - // TODO - // Set contextual information that can be reused during the storage phase. - // @todo Remove this once translation metadata are converted to regular - // fields. - $attributes = \Drupal::request()->attributes; - $attributes->set('source_langcode', $source_langcode); } /** diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSyncImageTest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSyncImageTest.php index f974837..c5e8d9b 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSyncImageTest.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationSyncImageTest.php @@ -122,10 +122,6 @@ function testImageFieldSync() { $default_langcode = $this->langcodes[0]; $langcode = $this->langcodes[1]; - // Populate the required contextual values. - $attributes = $this->container->get('request')->attributes; - $attributes->set('source_langcode', $default_langcode); - // Populate the test entity with some random initial values. $values = array( 'name' => $this->randomName(), @@ -193,6 +189,7 @@ function testImageFieldSync() { // Perform synchronization: the translation language is used as source, // while the default language is used as target. + $translation->translation_source->id = $default_langcode; $entity = $this->saveEntity($translation); $translation = $entity->getTranslation($langcode); @@ -222,8 +219,6 @@ function testImageFieldSync() { 'title' => $langcode . '_' . $removed_fid . '_' . $this->randomName(), ); $translation->{$this->fieldName}->setValue(array_values($values[$langcode])); - // When updating an entity we do not have a source language defined. - $attributes->remove('source_langcode'); $entity = $this->saveEntity($translation); $translation = $entity->getTranslation($langcode);