reverted: --- b/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php +++ a/core/modules/hal/src/Normalizer/ContentEntityNormalizer.php @@ -146,6 +146,8 @@ break; } } + // Remove the default langcode so it does not get iterated over below. + unset($data[$default_langcode_key]); } if ($entity_type->hasKey('bundle')) { reverted: --- b/core/modules/hal/src/Normalizer/FieldItemNormalizer.php +++ a/core/modules/hal/src/Normalizer/FieldItemNormalizer.php @@ -2,9 +2,7 @@ namespace Drupal\hal\Normalizer; -use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldItemInterface; -use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\TypedData\TypedDataInternalPropertiesHelper; use Drupal\serialization\Normalizer\FieldableEntityNormalizerTrait; use Drupal\serialization\Normalizer\SerializedColumnNormalizerTrait; @@ -122,43 +120,9 @@ // Instead, create a new item for the entity in the requested language. $entity = $item->getEntity(); + $entity_translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode); - // Get the translated entity, or create it if it does not exist. - $entity_translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $this->createTranslatedEntity($entity, $langcode); $field_name = $item->getFieldDefinition()->getName(); + return $entity_translation->get($field_name)->appendItem(); - $field = $entity_translation->get($field_name); - $cardinality = $item->getFieldDefinition()->getFieldStorageDefinition()->getCardinality(); - if ($cardinality === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || count($field) < $cardinality) { - return $field->appendItem(); - } - return $field->first(); - } - - /** - * Create an empty entity translation to fill with field data. - * - * @param \Drupal\Core\Entity\FieldableEntityInterface $entity - * The untranslated entity. - * @param string $langcode - * The langcode. - * - * @return \Drupal\Core\Entity\FieldableEntityInterface - * The translated entity. - * - * @throws \Drupal\Core\TypedData\Exception\ReadOnlyException - */ - protected function createTranslatedEntity(FieldableEntityInterface $entity, $langcode) { - // Create a new translation. - /** @var \Drupal\Core\TypedData\TranslatableInterface $entity */ - /** @var \Drupal\Core\Entity\FieldableEntityInterface $entity_translation */ - $entity_translation = $entity->addTranslation($langcode); - - // Remove all default values, except for the langcode. - $translated_fields = $entity_translation->getTranslatableFields(FALSE); - unset($translated_fields['langcode']); - foreach ($translated_fields as $field) { - $field->setValue([]); - } - return $entity_translation; } /** reverted: --- b/core/modules/hal/tests/src/Kernel/TranslationNormalizeTest.php +++ /dev/null @@ -1,48 +0,0 @@ -installEntitySchema('entity_test_mul_changed'); - } - - /** - * Tests normalizing and denormalizing an entity. - */ - public function testTranslationNormalize() { - $target_entity = EntityTestMulChanged::create((['langcode' => 'en', 'field_test_entity_reference' => NULL])); - $target_entity->save(); - - $target_entity->addTranslation('de', $target_entity->toArray()); - - $this->assertEquals(1, count($target_entity->changed)); - $this->assertEquals(1, count($target_entity->getTranslation('en')->changed)); - $this->assertEquals(1, count($target_entity->getTranslation('de')->changed)); - - $data = $this->serializer->normalize($target_entity, 'hal_json'); - $denormalized_entity = $this->serializer->denormalize($data, $this->entityClass, 'hal_json'); - - $this->assertEquals(1, count($denormalized_entity->changed)); - $this->assertEquals(1, count($target_entity->getTranslation('en')->changed)); - $this->assertEquals(1, count($denormalized_entity->getTranslation('de')->changed)); - } - -} only in patch2: unchanged: --- a/src/Normalizer/ContentEntityNormalizer.php +++ b/src/Normalizer/ContentEntityNormalizer.php @@ -146,8 +146,6 @@ class ContentEntityNormalizer extends NormalizerBase { break; } } - // Remove the default langcode so it does not get iterated over below. - unset($data[$default_langcode_key]); } if ($entity_type->hasKey('bundle')) { only in patch2: unchanged: --- a/src/Normalizer/FieldItemNormalizer.php +++ b/src/Normalizer/FieldItemNormalizer.php @@ -2,7 +2,9 @@ namespace Drupal\hal\Normalizer; +use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Field\FieldItemInterface; +use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\TypedData\TypedDataInternalPropertiesHelper; use Drupal\serialization\Normalizer\FieldableEntityNormalizerTrait; use Drupal\serialization\Normalizer\SerializedColumnNormalizerTrait; @@ -120,9 +122,43 @@ class FieldItemNormalizer extends NormalizerBase { // Instead, create a new item for the entity in the requested language. $entity = $item->getEntity(); - $entity_translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode); + // Get the translated entity, or create it if it does not exist. + $entity_translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $this->createTranslatedEntity($entity, $langcode); $field_name = $item->getFieldDefinition()->getName(); - return $entity_translation->get($field_name)->appendItem(); + $field = $entity_translation->get($field_name); + $cardinality = $item->getFieldDefinition()->getFieldStorageDefinition()->getCardinality(); + if ($cardinality === FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED || count($field) < $cardinality) { + return $field->appendItem(); + } + return $field->first(); + } + + /** + * Create an empty entity translation to fill with field data. + * + * @param \Drupal\Core\Entity\FieldableEntityInterface $entity + * The untranslated entity. + * @param string $langcode + * The langcode. + * + * @return \Drupal\Core\Entity\FieldableEntityInterface + * The translated entity. + * + * @throws \Drupal\Core\TypedData\Exception\ReadOnlyException + */ + protected function createTranslatedEntity(FieldableEntityInterface $entity, $langcode) { + // Create a new translation. + /** @var \Drupal\Core\TypedData\TranslatableInterface $entity */ + /** @var \Drupal\Core\Entity\FieldableEntityInterface $entity_translation */ + $entity_translation = $entity->addTranslation($langcode); + + // Remove all default values, except for the langcode. + $translated_fields = $entity_translation->getTranslatableFields(FALSE); + unset($translated_fields['langcode']); + foreach ($translated_fields as $field) { + $field->setValue([]); + } + return $entity_translation; } /** only in patch2: unchanged: --- /dev/null +++ b/tests/src/Kernel/TranslationNormalizeTest.php @@ -0,0 +1,48 @@ +installEntitySchema('entity_test_mul_changed'); + } + + /** + * Tests normalizing and denormalizing an entity. + */ + public function testTranslationNormalize() { + $target_entity = EntityTestMulChanged::create((['langcode' => 'en', 'field_test_entity_reference' => NULL])); + $target_entity->save(); + + $target_entity->addTranslation('de', $target_entity->toArray()); + + $this->assertEquals(1, count($target_entity->changed)); + $this->assertEquals(1, count($target_entity->getTranslation('en')->changed)); + $this->assertEquals(1, count($target_entity->getTranslation('de')->changed)); + + $data = $this->serializer->normalize($target_entity, 'hal_json'); + $denormalized_entity = $this->serializer->denormalize($data, $this->entityClass, 'hal_json'); + + $this->assertEquals(1, count($denormalized_entity->changed)); + $this->assertEquals(1, count($target_entity->getTranslation('en')->changed)); + $this->assertEquals(1, count($denormalized_entity->getTranslation('de')->changed)); + } + +}