namespace Drupal\content_translation\Controller;
+use Drupal\content_translation\ContentTranslationManager;
use Drupal\content_translation\ContentTranslationManagerInterface;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Controller\ControllerBase;
$handler = $this->entityManager()->getHandler($entity_type_id, 'translation');
$manager = $this->manager;
$entity_type = $entity->getEntityType();
+ $use_latest_revisions = $entity_type->isRevisionable() && ContentTranslationManager::isPendingRevisionSupportEnabled($entity_type_id, $entity->bundle());
// Start collecting the cacheability metadata, starting with the entity and
// later merge in the access result cacheability metadata.
$rows = [];
$show_source_column = FALSE;
+ /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
+ $storage = $this->entityTypeManager()->getStorage($entity_type_id);
+ $default_revision = $storage->load($entity->id());
if ($this->languageManager()->isMultilingual()) {
// Determine whether the current entity is translatable.
$language_name = $language->getName();
$langcode = $language->getId();
- $add_url = new Url(
- "entity.$entity_type_id.content_translation_add",
- [
- 'source' => $original,
- 'target' => $language->getId(),
- $entity_type_id => $entity->id(),
- ],
- [
- 'language' => $language,
- ]
- );
- $edit_url = new Url(
- "entity.$entity_type_id.content_translation_edit",
- [
- 'language' => $language->getId(),
- $entity_type_id => $entity->id(),
- ],
- [
- 'language' => $language,
- ]
- );
- $delete_url = new Url(
- "entity.$entity_type_id.content_translation_delete",
- [
- 'language' => $language->getId(),
- $entity_type_id => $entity->id(),
- ],
- [
- 'language' => $language,
- ]
- );
+ // If the entity type is revisionable, we may have pending revisions
+ // with translations not available yet in the default revision. Thus we
+ // need to load the latest translation-affecting revision for each
+ // language to be sure we are listing all available translations.
+ if ($use_latest_revisions) {
+ $entity = $default_revision;
+ $latest_revision_id = $storage->getLatestTranslationAffectedRevisionId($entity->id(), $langcode);
+ if ($latest_revision_id) {
+ /** @var \Drupal\Core\Entity\ContentEntityInterface $latest_revision */
+ $latest_revision = $storage->loadRevision($latest_revision_id);
+ // Make sure we do not list removed translations, i.e. translations
+ // that have been part of a default revision but no longer are.
+ if (!$latest_revision->wasDefaultRevision() || $default_revision->hasTranslation($langcode)) {
+ $entity = $latest_revision;
+ }
+ }
+ $translations = $entity->getTranslationLanguages();
+ }
+
+ $options = ['language' => $language];
+ $add_url = $entity->toUrl('drupal:content-translation-add', $options)
+ ->setRouteParameter('source', $original)
+ ->setRouteParameter('target', $language->getId());
+ $edit_url = $entity->toUrl('drupal:content-translation-edit', $options)
+ ->setRouteParameter('language', $language->getId());
+ $delete_url = $entity->toUrl('drupal:content-translation-delete', $options)
+ ->setRouteParameter('language', $language->getId());
$operations = [
'data' => [
'#type' => 'operations',
$source_name = $this->t('n/a');
}
else {
- $source_name = isset($languages[$source]) ? $languages[$source]->getName() : $this->t('n/a');
- $delete_access = $entity->access('delete', NULL, TRUE);
- $translation_access = $handler->getTranslationAccess($entity, 'delete');
- $cacheability = $cacheability
- ->merge(CacheableMetadata::createFromObject($delete_access))
- ->merge(CacheableMetadata::createFromObject($translation_access));
- if ($entity->access('delete') && $entity_type->hasLinkTemplate('delete-form')) {
- $links['delete'] = [
- 'title' => $this->t('Delete'),
- 'url' => $entity->urlInfo('delete-form'),
- 'language' => $language,
- ];
+ /** @var \Drupal\Core\Access\AccessResultInterface $delete_route_access */
+ $delete_route_access = \Drupal::service('content_translation.delete_access')->checkAccess($translation);
+ $cacheability->addCacheableDependency($delete_route_access);
+
+ if ($delete_route_access->isAllowed()) {
+ $source_name = isset($languages[$source]) ? $languages[$source]->getName() : $this->t('n/a');
+ $delete_access = $entity->access('delete', NULL, TRUE);
+ $translation_access = $handler->getTranslationAccess($entity, 'delete');
+ $cacheability
+ ->addCacheableDependency($delete_access)
+ ->addCacheableDependency($translation_access);
+
+ if ($delete_access->isAllowed() && $entity_type->hasLinkTemplate('delete-form')) {
+ $links['delete'] = [
+ 'title' => $this->t('Delete'),
+ 'url' => $entity->urlInfo('delete-form'),
+ 'language' => $language,
+ ];
+ }
+ elseif ($translation_access->isAllowed()) {
+ $links['delete'] = [
+ 'title' => $this->t('Delete'),
+ 'url' => $delete_url,
+ ];
+ }
}
- elseif ($translation_access->isAllowed()) {
- $links['delete'] = [
- 'title' => $this->t('Delete'),
- 'url' => $delete_url,
- ];
+ else {
+ $this->messenger()->addWarning($this->t('The "Delete translation" action is only available for published translations.'), FALSE);
}
}
}
* A processed form array ready to be rendered.
*/
public function add(LanguageInterface $source, LanguageInterface $target, RouteMatchInterface $route_match, $entity_type_id = NULL) {
+ /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
$entity = $route_match->getParameter($entity_type_id);
+ // In case of a pending revision, make sure we load the latest
+ // translation-affecting revision for the source language, otherwise the
+ // initial form values may not be up-to-date.
+ if (!$entity->isDefaultRevision() && ContentTranslationManager::isPendingRevisionSupportEnabled($entity_type_id, $entity->bundle())) {
+ /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
+ $storage = $this->entityTypeManager()->getStorage($entity->getEntityTypeId());
+ $revision_id = $storage->getLatestTranslationAffectedRevisionId($entity->id(), $source->getId());
+ if ($revision_id != $entity->getRevisionId()) {
+ $entity = $storage->loadRevision($revision_id);
+ }
+ }
+
// @todo Exploit the upcoming hook_entity_prepare() when available.
// See https://www.drupal.org/node/1810394.
$this->prepareTranslation($entity, $source, $target);