0

Was there any significant change in how translatable custom entities are updated leading up to Drupal 10.1? There are a few questions here that deal with the question but it no longer seems to work. To recap, I have a custom entity already populated with data that I want to make translatable now. I have made all the necessary changes: the entity itself is annotated to be translatable, entity key added, two langcode fields added, translation handler added. Actually, if I temporarily remove the data and use Devel's entup, it works. Still, I want to make it able to do the correct data migration.

I have both update functions in place:

function MODULE_update_VERSION() {
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $field_storage_definition = $entity_definition_update_manager->getFieldStorageDefinition('my_field', 'my_entity');
  $field_storage_definition->setTranslatable(TRUE);
  $entity_definition_update_manager->updateFieldStorageDefinition($field_storage_definition);
}

and

function MODULE_post_update_VERSION(&$sandbox) {
  $definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = $definition_update_manager->getEntityType('my_entity');
  $entity_type->set('translatable', TRUE);
  $entity_type->set('data_table', 'my_entity_field_data');

  /** @var EntityLastInstalledSchemaRepositoryInterface $last_installed_schema_repository */
  $last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
  $field_storage_definitions = $last_installed_schema_repository->getLastInstalledFieldStorageDefinitions('my_entity');
  $field_storage_definitions['my_field']->setTranslatable(TRUE);

  $field_storage_definitions['langcode'] = BaseFieldDefinition::create('language')
    ->setName('langcode')
    ->setLabel(t('Language code'))
    ->setDescription(t('The language code.'))
    ->setStorageRequired(TRUE)
    ->setDefaultValue('x-default')
    ->setTranslatable(TRUE);

  $field_storage_definitions['default_langcode'] = BaseFieldDefinition::create('boolean')
    ->setName('default_langcode')
    ->setLabel(t('Default Language code'))
    ->setDescription(t('Indicates if this is the default language.'))
    ->setTargetEntityTypeId('my_entity')
    ->setTargetBundle(NULL)
    ->setTranslatable(TRUE)
    ->setRevisionable(TRUE)
    ->setDefaultValue(TRUE);

  $definition_update_manager->updateFieldableEntityType($entity_type, $field_storage_definitions, $sandbox);
}

When updating (either Drush or UI), both update functions are picked up, however, while the regular update succeeds, the post update function gives a Missing langcode field error and stops.

The langcode field is obviously right there, to be created. I thought about splitting the action into two upgrade steps, first langcode and default_langcode, then doing the migration, but while the fields do appear in the base table then, the error message is the same.

So, the question is whether there was any change, intentional or not in later Drupal versions that makes this approach fail now?

1 Answer 1

2

Indeed, the items above are no longer sufficient, some others have to be specified as well:

  $definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = $definition_update_manager->getEntityType('my_entity');
  $entity_keys = $entity_type->getKeys(); // <<<
  $entity_keys['langcode'] = 'langcode'; // <<<
  $entity_keys['default_langcode'] = 'default_langcode'; // <<<
  $entity_type->set('entity_keys', $entity_keys); // <<<
  $entity_type->set('translatable', TRUE);
  $entity_type->set('data_table', 'my_entity_field_data');

The error message is actually misleading, it's not the field that's missing but its key.

Also (this didn't seem to be necessary earlier):

  $field_storage_definitions['langcode'] = BaseFieldDefinition::create('language')
   ->setName('default_langcode')
    ->setLabel(t('Default Language code'))
    ->setDescription(t('Indicates if this is the default language.'))
    ->setTargetEntityTypeId('my_entity') // <<<
    ->setTargetBundle(NULL)
    ->setTranslatable(TRUE)
    ->setRevisionable(TRUE)
    ->setDefaultValue(TRUE);

Addendum:

->setDefaultValue('x-default')

is very questionable. Some other sources mentioned it but it doesn't seem to work. Proceed with care, maybe use the actual default language code of your site. Drupal used to call it und some time ago, I don't know if that would still work here or not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.