diff --git a/core/modules/config_translation/src/ConfigTranslation/EntityDisplayMapper.php b/core/modules/config_translation/src/ConfigTranslation/EntityDisplayMapper.php new file mode 100644 index 00000000..98d75c45 --- /dev/null +++ b/core/modules/config_translation/src/ConfigTranslation/EntityDisplayMapper.php @@ -0,0 +1,112 @@ +entityTypeManager + ->getDefinition($this->pluginDefinition['base_entity_type']); + $bundle_parameter_key = $base_entity_info + ->getBundleEntityType() ?: 'bundle'; + + $parameters = []; + $parameters[$bundle_parameter_key] = $this->entity->getTargetBundle(); + $parameters[$this->pluginDefinition['display_context'] . '_mode_name'] = $this->entity->getMode(); + + return $parameters; + } + + /** + * {@inheritdoc} + */ + public function getOverviewRouteName() { + return "entity.{$this->entityType}.config_translation_overview.{$this->pluginDefinition['base_entity_type']}"; + } + + /** + * {@inheritdoc} + */ + public function getTitle() { + $base_entity_info = $this->entityTypeManager + ->getDefinition($this->pluginDefinition['base_entity_type']); + $bundle = $base_entity_info->getLabel(); + if ($bundle_type = $base_entity_info->getBundleEntityType()) { + $bundle = $this->entityTypeManager + ->getStorage($bundle_type) + ->load($this->entity->getTargetBundle()) + ->label(); + } + + $mode = $this->entityTypeManager + ->getStorage("entity_{$this->pluginDefinition['display_context']}_mode") + ->load($this->pluginDefinition['base_entity_type'] . '.' . $this->entity->getMode()); + $mode = $mode ? $mode->label() : $this->t('Default'); + + if ($this->entityType == 'entity_view_display') { + return $this->t('@bundle @mode display', [ + '@bundle' => $bundle, + '@mode' => $mode, + ]); + } + elseif ($this->entityType == 'entity_form_display') { + return $this->t('@bundle @mode form display', [ + '@bundle' => $bundle, + '@mode' => $mode, + ]); + } + parent::getTypeLabel(); + } + + /** + * {@inheritdoc} + */ + public function getTypeLabel() { + $base_entity_info = $this->entityTypeManager + ->getDefinition($this->pluginDefinition['base_entity_type']); + + if ($this->entityType == 'entity_view_display') { + return $this->t('@label view display', [ + '@label' => $base_entity_info->getLabel(), + ]); + } + elseif ($this->entityType == 'entity_form_display') { + return $this->t('@label form display', [ + '@label' => $base_entity_info->getLabel(), + ]); + } + parent::getTypeLabel(); + } + + /** + * {@inheritdoc} + */ + public function populateFromRouteMatch(RouteMatchInterface $route_match) { + $bundle_entity_type = $this->entityTypeManager + ->getDefinition($this->pluginDefinition['base_entity_type']) + ->getBundleEntityType(); + $bundle = $route_match->getParameter($bundle_entity_type ?: 'bundle') ?: $this->pluginDefinition['base_entity_type']; + $mode = $route_match->getParameter($this->pluginDefinition['display_context'] . '_mode_name') ?: 'default'; + + $entity = $this->entityTypeManager + ->getStorage($this->entityType) + ->load("{$this->pluginDefinition['base_entity_type']}.{$bundle}.{$mode}"); + + if ($entity) { + $route_match->getParameters()->set($this->entityType, $entity); + + $this->setEntity($entity); + parent::populateFromRouteMatch($route_match); + } + } + +} diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationEntityDisplayListBuilder.php b/core/modules/config_translation/src/Controller/ConfigTranslationEntityDisplayListBuilder.php new file mode 100644 index 00000000..b24e46f2 --- /dev/null +++ b/core/modules/config_translation/src/Controller/ConfigTranslationEntityDisplayListBuilder.php @@ -0,0 +1,117 @@ +displayContext = preg_replace('/^entity_(.+)_display$/', '\1', $this->entityType->id()); + } + + /** + * {@inheritdoc} + */ + public function load() { + // It is not possible to use the standard load method, because this needs + // all display entities only for the given baseEntityType. + $ids = \Drupal::entityQuery($this->entityType->id()) + ->condition('id', $this->baseEntityType . '.', 'STARTS_WITH') + ->execute(); + return $this->storage->loadMultiple($ids); + } + + /** + * {@inheritdoc} + */ + public function getFilterLabels() { + $info = parent::getFilterLabels(); + $bundle = $this->baseEntityInfo->getBundleLabel() ?: $this->t('Bundle'); + $bundle = mb_strtolower($bundle); + $info['placeholder'] = $this->t('Enter mode or @bundle', [ + '@bundle' => $bundle, + ]); + $info['description'] = $this->t('Enter a part of the mode or @bundle to filter by.', [ + '@bundle' => $bundle, + ]); + return $info; + } + + /** + * {@inheritdoc} + */ + public function buildRow(EntityInterface $entity) { + $row = parent::buildRow($entity); + $row['label']['data'] = $entity->getMode() == 'default' ? $this->t('Default') : $this->entityTypeManager + ->getStorage('entity_' . $this->displayContext . '_mode') + ->load($entity->getTargetEntityTypeId() . '.' . $entity->getMode()) + ->label(); + return $row; + } + + /** + * {@inheritdoc} + */ + public function buildHeader() { + $header = parent::buildHeader(); + $header['label'] = $this->entityType->getLabel(); + return $header; + } + + /** + * {@inheritdoc} + */ + public function getOperations(EntityInterface $entity) { + // Entity displays have no canonical no direct edit-form links so we + // hard-code the route to the translation operation. + // @todo Use config-translation-overview link template like field_ui does. + $route_parameters = [ + $this->displayContext . '_mode_name' => $entity->getMode(), + ]; + + $bundle_type = $this->entityTypeManager + ->getDefinition($entity->getTargetEntityTypeId()) + ->getBundleEntityType(); + if ($bundle_type) { + $route_parameters[$bundle_type] = $entity->getTargetBundle(); + } + + $operations['translate'] = [ + 'title' => $this->t('Translate'), + 'url' => $this->ensureDestination(Url::fromRoute("entity.{$this->entityType->id()}.config_translation_overview.{$entity->getTargetEntityTypeId()}", $route_parameters)), + ]; + + return $operations; + } + +} diff --git a/core/modules/config_translation/src/Hook/ConfigTranslationHooks.php b/core/modules/config_translation/src/Hook/ConfigTranslationHooks.php index 21daa8b7..bca9d4eb 100644 --- a/core/modules/config_translation/src/Hook/ConfigTranslationHooks.php +++ b/core/modules/config_translation/src/Hook/ConfigTranslationHooks.php @@ -8,6 +8,9 @@ use Drupal\Core\Config\Entity\ConfigEntityInterface; use Drupal\Core\Url; use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\Core\Entity\Display\EntityDisplayInterface; +use Drupal\config_translation\ConfigTranslation\EntityDisplayMapper; +use Drupal\config_translation\Controller\ConfigTranslationEntityDisplayListBuilder; use Drupal\Core\Hook\Attribute\Hook; /** @@ -119,6 +122,10 @@ public function entityTypeAlter(array &$entity_types) : void { // \Drupal\field\Entity\FieldConfig::linkTemplates(). $entity_type->setLinkTemplate('config-translation-overview', $entity_type->getLinkTemplate('edit-form') . '/translate'); } + elseif ($entity_type->entityClassImplements(EntityDisplayInterface::class)) { + $class = ConfigTranslationEntityDisplayListBuilder::class; + // @todo Link template is not used but should be set so other logic can apply. + } else { $class = 'Drupal\config_translation\Controller\ConfigTranslationEntityListBuilder'; } @@ -150,6 +157,22 @@ public function configTranslationInfo(&$info): void { 'base_entity_type' => $entity_type_id, 'weight' => 10, ]; + $info[$entity_type_id . '_form_display'] = [ + 'base_route_name' => "entity.entity_form_display.{$entity_type_id}.form_mode", + 'entity_type' => 'entity_form_display', + 'class' => EntityDisplayMapper::class, + 'base_entity_type' => $entity_type_id, + 'display_context' => 'form', + 'weight' => 10, + ]; + $info[$entity_type_id . '_view_display'] = [ + 'base_route_name' => "entity.entity_view_display.{$entity_type_id}.view_mode", + 'entity_type' => 'entity_view_display', + 'class' => EntityDisplayMapper::class, + 'base_entity_type' => $entity_type_id, + 'display_context' => 'view', + 'weight' => 10, + ]; } } }