Same name and namespace in other branches
  1. 8.9.x core/modules/content_translation/content_translation.module \content_translation_entity_type_alter()
  2. 9 core/modules/content_translation/content_translation.module \content_translation_entity_type_alter()

Implements hook_entity_type_alter().

The content translation UI relies on the entity info to provide its features. See the documentation of hook_entity_type_build() in the Entity API documentation for more details on all the entity info keys that may be defined.

To make Content Translation automatically support an entity type some keys may need to be defined, but none of them is required unless the entity path is different from the usual /ENTITY_TYPE/{ENTITY_TYPE} pattern (for instance "/taxonomy/term/{taxonomy_term}"). Here are a list of those optional keys:

  • canonical: This key (in the 'links' entity info property) must be defined if the entity path is different from /ENTITY_TYPE/{ENTITY_TYPE}
  • translation: This key (in the 'handlers' entity annotation property) specifies the translation handler for the entity type. If an entity type is translatable and no translation handler is defined, \Drupal\content_translation\ContentTranslationHandler will be assumed. Every translation handler must implement \Drupal\content_translation\ContentTranslationHandlerInterface.
  • content_translation_ui_skip: By default, entity types that do not have a canonical link template cannot be enabled for translation. Setting this key to TRUE overrides that. When that key is set, the Content Translation module will not provide any UI for translating the entity type, and the entity type should implement its own UI. For instance, this is useful for entity types that are embedded into others for editing (which would not need a canonical link, but could still support translation).
  • content_translation_metadata: To implement its business logic the content translation UI relies on various metadata items describing the translation state. The default implementation is provided by \Drupal\content_translation\ContentTranslationMetadataWrapper, which is relying on one field for each metadata item (field definitions are provided by the translation handler). Entity types needing to customize this behavior can specify an alternative class through the 'content_translation_metadata' key in the entity type definition. Every content translation metadata wrapper needs to implement \Drupal\content_translation\ContentTranslationMetadataWrapperInterface.

If the entity paths match the default pattern above and there is no need for an entity-specific translation handler, Content Translation will provide built-in support for the entity. However enabling translation for each translatable bundle will be required.

See also

\Drupal\Core\Entity\Annotation\EntityType

File

core/modules/content_translation/content_translation.module, line 133
Allows entities to be translated into different languages.

Code

function content_translation_entity_type_alter(array &$entity_types) {

  // Provide defaults for translation info.

  /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
  foreach ($entity_types as $entity_type) {
    if ($entity_type
      ->isTranslatable()) {
      if (!$entity_type
        ->hasHandlerClass('translation')) {
        $entity_type
          ->setHandlerClass('translation', 'Drupal\\content_translation\\ContentTranslationHandler');
      }
      if (!$entity_type
        ->get('content_translation_metadata')) {
        $entity_type
          ->set('content_translation_metadata', 'Drupal\\content_translation\\ContentTranslationMetadataWrapper');
      }
      if (!$entity_type
        ->getFormClass('content_translation_deletion')) {
        $entity_type
          ->setFormClass('content_translation_deletion', '\\Drupal\\content_translation\\Form\\ContentTranslationDeleteForm');
      }
      $translation = $entity_type
        ->get('translation');
      if (!$translation || !isset($translation['content_translation'])) {
        $translation['content_translation'] = [];
      }
      if ($entity_type
        ->hasLinkTemplate('canonical')) {

        // Provide default route names for the translation paths.
        if (!$entity_type
          ->hasLinkTemplate('drupal:content-translation-overview')) {
          $translations_path = $entity_type
            ->getLinkTemplate('canonical') . '/translations';
          $entity_type
            ->setLinkTemplate('drupal:content-translation-overview', $translations_path);
          $entity_type
            ->setLinkTemplate('drupal:content-translation-add', $translations_path . '/add/{source}/{target}');
          $entity_type
            ->setLinkTemplate('drupal:content-translation-edit', $translations_path . '/edit/{language}');
          $entity_type
            ->setLinkTemplate('drupal:content-translation-delete', $translations_path . '/delete/{language}');
        }

        // @todo Remove this as soon as menu access checks rely on the
        //   controller. See https://www.drupal.org/node/2155787.
        $translation['content_translation'] += [
          'access_callback' => 'content_translation_translate_access',
        ];
      }
      $entity_type
        ->set('translation', $translation);
    }
    $entity_type
      ->addConstraint('ContentTranslationSynchronizedFields');
  }
}