diff --git a/config/schema/entity.schema.yml b/config/schema/entity.schema.yml
index a70ef2a1fb704a377884034785bf44140b9a44d2..b3c19235842c0e15f1caa27f55071087a85bb5e9 100644
--- a/config/schema/entity.schema.yml
+++ b/config/schema/entity.schema.yml
@@ -1,3 +1,7 @@
+action.configuration.entity_delete_action:*:
+  type: action_configuration_default
+  label: 'Delete entity configuration'
+
 views.field.rendered_entity:
   type: views_field
   label: 'Rendered entity'
diff --git a/src/Form/DeleteMultiple.php b/src/Form/DeleteMultiple.php
new file mode 100644
index 0000000000000000000000000000000000000000..7fe04ff5e95ae23c9f7df5223e0bfc1eda31e60c
--- /dev/null
+++ b/src/Form/DeleteMultiple.php
@@ -0,0 +1,231 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Form\DeleteMultiple.
+ */
+
+namespace Drupal\entity\Form;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\Core\Url;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\user\PrivateTempStoreFactory;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides an entities deletion confirmation form.
+ */
+class DeleteMultiple extends ConfirmFormBase {
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The tempstore.
+   *
+   * @var \Drupal\user\SharedTempStore
+   */
+  protected $tempStore;
+
+  /**
+   * The entity type id.
+   *
+   * @var string
+   */
+  protected $entityTypeId;
+
+  /**
+   * The selection, in the entity_id => langcodes format.
+   *
+   * @var array
+   */
+  protected $selection = [];
+
+  /**
+   * Constructs a new DeleteMultiple object.
+   *
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
+   *   The tempstore factory.
+   */
+  public function __construct(AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, PrivateTempStoreFactory $temp_store_factory) {
+    $this->currentUser = $current_user;
+    $this->entityTypeManager = $entity_type_manager;
+    $this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('current_user'),
+      $container->get('entity_type.manager'),
+      $container->get('user.private_tempstore')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'entity_delete_multiple_confirm';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQuestion() {
+    return $this->formatPlural(count($this->selection), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCancelUrl() {
+    return new Url('entity.' . $this->entityTypeId . '.collection');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfirmText() {
+    return $this->t('Delete');
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param string $entity_type_id
+   *   The entity type id.
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) {
+    $this->entityTypeId = $entity_type_id;
+    $this->selection = $this->tempStore->get($this->currentUser->id());
+    if (empty($this->entityTypeId) || empty($this->selection)) {
+      return new RedirectResponse($this->getCancelUrl()->setAbsolute()->toString());
+    }
+
+    $storage = $this->entityTypeManager->getStorage($this->entityTypeId);
+    /** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
+    $entities = $storage->loadMultiple(array_keys($this->selection));
+    $items = [];
+    foreach ($this->selection as $id => $langcodes) {
+      foreach ($langcodes as $langcode) {
+        $entity = $entities[$id]->getTranslation($langcode);
+        $key = $id . ':' . $langcode;
+        $default_key = $id . ':' . $entity->getUntranslated()->language()->getId();
+
+        // If we have a translated entity we build a nested list of translations
+        // that will be deleted.
+        $languages = $entity->getTranslationLanguages();
+        if (count($languages) > 1 && $entity->isDefaultTranslation()) {
+          $names = [];
+          foreach ($languages as $translation_langcode => $language) {
+            $names[] = $language->getName();
+            unset($items[$id . ':' . $translation_langcode]);
+          }
+          $items[$default_key] = [
+            'label' => [
+              '#markup' => $this->t('@label (Original translation) - <em>The following translations will be deleted:</em>', ['@label' => $entity->label()]),
+            ],
+            'deleted_translations' => [
+              '#theme' => 'item_list',
+              '#items' => $names,
+            ],
+          ];
+        }
+        elseif (!isset($items[$default_key])) {
+          $items[$key] = $entity->label();
+        }
+      }
+    }
+
+    $form['entities'] = [
+      '#theme' => 'item_list',
+      '#items' => $items,
+    ];
+    $form = parent::buildForm($form, $form_state);
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $total_count = 0;
+    $delete_entities = [];
+    $delete_translations = [];
+    $storage = $this->entityTypeManager->getStorage($this->entityTypeId);
+    /** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
+    $entities = $storage->loadMultiple(array_keys($this->selection));
+
+    foreach ($this->selection as $id => $langcodes) {
+      foreach ($langcodes as $langcode) {
+        $entity = $entities[$id]->getTranslation($langcode);
+        if ($entity->isDefaultTranslation()) {
+          $delete_entities[$id] = $entity;
+          unset($delete_translations[$id]);
+          $total_count += count($entity->getTranslationLanguages());
+        }
+        elseif (!isset($delete_entities[$id])) {
+          $delete_translations[$id][] = $entity;
+        }
+      }
+    }
+
+    if ($delete_entities) {
+      $storage->delete($delete_entities);
+      $this->logger('content')->notice('Deleted @count @entity_type items.', [
+        '@count' => count($delete_entities),
+        '@entity_type' => $this->entityTypeId,
+      ]);
+    }
+
+    if ($delete_translations) {
+      $count = 0;
+      /** @var \Drupal\Core\Entity\ContentEntityInterface[][] $delete_translations */
+      foreach ($delete_translations as $id => $translations) {
+        $entity = $entities[$id]->getUntranslated();
+        foreach ($translations as $translation) {
+          $entity->removeTranslation($translation->language()->getId());
+        }
+        $entity->save();
+        $count += count($translations);
+      }
+      if ($count) {
+        $total_count += $count;
+        $this->logger('content')->notice('Deleted @count @entity_type translations.', [
+          '@count' => $count,
+          '@entity_type' => $this->entityTypeId,
+        ]);
+      }
+    }
+
+    if ($total_count) {
+      drupal_set_message($this->formatPlural($total_count, 'Deleted 1 item.', 'Deleted @count items.'));
+    }
+    $this->tempStore->delete($this->currentUser->id());
+    $form_state->setRedirectUrl($this->getCancelUrl());
+  }
+
+}
diff --git a/src/Plugin/Action/DeleteAction.php b/src/Plugin/Action/DeleteAction.php
new file mode 100644
index 0000000000000000000000000000000000000000..8812fd56d9d7c60aa24f5c40cf6a0b0499fb58e1
--- /dev/null
+++ b/src/Plugin/Action/DeleteAction.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Plugin\Action\DeleteAction.
+ */
+
+namespace Drupal\entity\Plugin\Action;
+
+use Drupal\Core\Action\ActionBase;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\user\PrivateTempStoreFactory;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Redirects to an entity deletion form.
+ *
+ * @Action(
+ *   id = "entity_delete_action",
+ *   label = @Translation("Delete entity"),
+ *   deriver = "Drupal\entity\Plugin\Action\Derivative\DeleteActionDeriver",
+ * )
+ */
+class DeleteAction extends ActionBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The tempstore object.
+   *
+   * @var \Drupal\user\SharedTempStore
+   */
+  protected $tempStore;
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
+   * Constructs a new DeleteAction object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin ID for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
+   *   The tempstore factory.
+   * @param AccountInterface $current_user
+   *   Current user.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, PrivateTempStoreFactory $temp_store_factory, AccountInterface $current_user) {
+    $this->currentUser = $current_user;
+    $this->tempStore = $temp_store_factory->get('entity_delete_multiple_confirm');
+
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('user.private_tempstore'),
+      $container->get('current_user')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function executeMultiple(array $entities) {
+    /** @var \Drupal\Core\Entity\ContentEntityInterface[] $entities */
+    $selection = [];
+    foreach ($entities as $entity) {
+      $langcode = $entity->language()->getId();
+      $selection[$entity->id()][$langcode] = $langcode;
+    }
+    $this->tempStore->set($this->currentUser->id(), $selection);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute($object = NULL) {
+    $this->executeMultiple([$object]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
+    return $object->access('delete', $account, $return_as_object);
+  }
+
+}
diff --git a/src/Plugin/Action/Derivative/DeleteActionDeriver.php b/src/Plugin/Action/Derivative/DeleteActionDeriver.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c86bcc7c0edb4aafbe854ad4b70d16501f4bb78
--- /dev/null
+++ b/src/Plugin/Action/Derivative/DeleteActionDeriver.php
@@ -0,0 +1,83 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Plugin\Action\Derivative\DeleteActionDeriver.
+ */
+
+namespace Drupal\entity\Plugin\Action\Derivative;
+
+use Drupal\Component\Plugin\Derivative\DeriverBase;
+use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a delete action for each content entity type.
+ */
+class DeleteActionDeriver extends DeriverBase implements ContainerDeriverInterface {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * Constructs a new DeleteActionDeriver object.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   *   The entity type manager.
+   */
+  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
+    $this->entityTypeManager = $entity_type_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $base_plugin_id) {
+    return new static($container->get('entity_type.manager'));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDerivativeDefinitions($base_plugin_definition) {
+    if (empty($this->derivatives)) {
+      $definitions = [];
+      foreach ($this->getParticipatingEntityTypes() as $entity_type_id => $entity_type) {
+        $definition = $base_plugin_definition;
+        $definition['label'] = t('Delete @entity_type', ['@entity_type' => $entity_type->getLowercaseLabel()]);
+        $definition['type'] = $entity_type_id;
+        $definition['confirm_form_route_name'] = 'entity.' . $entity_type_id . '.delete_multiple_form';
+        $definitions[$entity_type_id] = $definition;
+      }
+      $this->derivatives = $definitions;
+    }
+
+    return parent::getDerivativeDefinitions($base_plugin_definition);
+  }
+
+  /**
+   * Gets a list of participating entity types.
+   *
+   * The list consists of all content entity types with a delete-multiple-form
+   * link template.
+   *
+   * @return \Drupal\Core\Entity\EntityTypeInterface[]
+   *   The participating entity types, keyed by entity type id.
+   */
+  protected function getParticipatingEntityTypes() {
+    $entity_types = $this->entityTypeManager->getDefinitions();
+    $entity_types = array_filter($entity_types, function (EntityTypeInterface $entity_type) {
+      return $entity_type->isSubclassOf(ContentEntityInterface::class) && $entity_type->hasLinkTemplate('delete-multiple-form');
+    });
+
+    return $entity_types;
+  }
+
+}
diff --git a/src/Routing/DeleteMultipleRouteProvider.php b/src/Routing/DeleteMultipleRouteProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..edbbc38291eb9863c1a68878445cdb651e884d67
--- /dev/null
+++ b/src/Routing/DeleteMultipleRouteProvider.php
@@ -0,0 +1,52 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\entity\Routing\DeleteMultipleRouteProvider.
+ */
+
+namespace Drupal\entity\Routing;
+
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Entity\Routing\EntityRouteProviderInterface;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Provides the HTML route for deleting multiple entities.
+ */
+class DeleteMultipleRouteProvider implements EntityRouteProviderInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRoutes(EntityTypeInterface $entity_type) {
+    $routes = new RouteCollection();
+    if ($route = $this->deleteMultipleFormRoute($entity_type)) {
+      $routes->add('entity.' . $entity_type->id() . '.delete_multiple_form', $route);
+    }
+
+    return $routes;
+  }
+
+  /**
+   * Returns the delete multiple form route.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *   The entity type.
+   *
+   * @return \Symfony\Component\Routing\Route|null
+   *   The generated route, if available.
+   */
+  protected function deleteMultipleFormRoute(EntityTypeInterface $entity_type) {
+    if ($entity_type->hasLinkTemplate('delete-multiple-form')) {
+      $route = new Route($entity_type->getLinkTemplate('delete-multiple-form'));
+      $route->setDefault('_form', '\Drupal\entity\Form\DeleteMultiple');
+      $route->setDefault('entity_type_id', $entity_type->id());
+      $route->setRequirement('_permission', $entity_type->getAdminPermission());
+
+      return $route;
+    }
+  }
+
+}
diff --git a/tests/modules/entity_module_test/config/schema/entity_module_test.schema.yml b/tests/modules/entity_module_test/config/schema/entity_module_test.schema.yml
index d4539912532484122d64f1b9a3e42f256d4fc693..eb1c5a089f08343de668ad896fd005a21a4a3e30 100644
--- a/tests/modules/entity_module_test/config/schema/entity_module_test.schema.yml
+++ b/tests/modules/entity_module_test/config/schema/entity_module_test.schema.yml
@@ -1,6 +1,6 @@
 entity_module_test.entity_test_enhanced_bundle.*:
   type: config_entity
-  label: 'Entity test with enhancments - Bundle'
+  label: 'Entity test with enhancements - Bundle'
   mapping:
     id:
       type: string
diff --git a/tests/modules/entity_module_test/entity_module_test.routing.yml b/tests/modules/entity_module_test/entity_module_test.routing.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3724a6524dfac2c86ae0f6bebf1199a87259b55e
--- /dev/null
+++ b/tests/modules/entity_module_test/entity_module_test.routing.yml
@@ -0,0 +1,7 @@
+entity.entity_test_enhanced.collection:
+  path: '/entity_test_enhanced'
+  defaults:
+    _entity_list: 'entity_test_enhanced'
+    _title: 'Entity test with enhancements'
+  requirements:
+    _permission: 'administer entity_test_enhanced'
diff --git a/tests/modules/entity_module_test/src/Entity/EnhancedEntity.php b/tests/modules/entity_module_test/src/Entity/EnhancedEntity.php
index 53c7ae441dc862b1ad97bd6f13c5dd6c4691954e..d199f3d653743818bc5cab93a4194190e1139bf5 100644
--- a/tests/modules/entity_module_test/src/Entity/EnhancedEntity.php
+++ b/tests/modules/entity_module_test/src/Entity/EnhancedEntity.php
@@ -30,7 +30,9 @@ use Drupal\entity\Revision\RevisionableContentEntityBase;
  *       "html" = "\Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
  *       "revision" = "\Drupal\entity\Routing\RevisionRouteProvider",
  *       "create" = "\Drupal\entity\Routing\CreateHtmlRouteProvider",
+ *       "delete-multiple" = "\Drupal\entity\Routing\DeleteMultipleRouteProvider",
  *     },
+ *     "list_builder" = "\Drupal\Core\Entity\EntityListBuilder",
  *   },
  *   base_table = "entity_test_enhanced",
  *   data_table = "entity_test_enhanced_field_data",
@@ -49,6 +51,8 @@ use Drupal\entity\Revision\RevisionableContentEntityBase;
  *     "add-page" = "/entity_test_enhanced/add",
  *     "add-form" = "/entity_test_enhanced/add/{type}",
  *     "canonical" = "/entity_test_enhanced/{entity_test_enhanced}",
+ *     "collection" = "/entity_test_enhanced",
+ *     "delete-multiple-form" = "/entity_test_enhanced/delete",
  *     "revision" = "/entity_test_enhanced/{entity_test_enhanced}/revisions/{entity_test_enhanced_revision}/view",
  *     "revision-revert-form" = "/entity_test_enhanced/{entity_test_enhanced}/revisions/{entity_test_enhanced_revision}/revert",
  *     "version-history" = "/entity_test_enhanced/{entity_test_enhanced}/revisions",
diff --git a/tests/src/Functional/DeleteMultipleFormTest.php b/tests/src/Functional/DeleteMultipleFormTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..50fb6cd8796cd45c19c22c18756d2e55ccfe06df
--- /dev/null
+++ b/tests/src/Functional/DeleteMultipleFormTest.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\entity\Functional\DeleteMultipleFormTest.
+ */
+
+namespace Drupal\Tests\entity\Functional;
+
+use Drupal\entity_module_test\Entity\EnhancedEntity;
+use Drupal\entity_module_test\Entity\EnhancedEntityBundle;
+use Drupal\simpletest\BrowserTestBase;
+
+/**
+ * Tests the delete multiple confirmation form.
+ *
+ * @group entity
+ * @runTestsInSeparateProcesses
+ * @preserveGlobalState disabled
+ */
+class DeleteMultipleFormTest extends BrowserTestBase {
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface;
+   */
+  protected $account;
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['entity_module_test', 'user', 'entity'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    EnhancedEntityBundle::create([
+      'id' => 'default',
+      'label' => 'Default',
+    ])->save();
+    $this->account = $this->drupalCreateUser(['administer entity_test_enhanced']);
+    $this->drupalLogin($this->account);
+  }
+
+  /**
+   * Tests the add page.
+   */
+  public function testForm() {
+    $entities = [];
+    $selection = [];
+    for ($i = 0; $i < 2; $i++) {
+      $entity = EnhancedEntity::create([
+        'type' => 'default',
+      ]);
+      $entity->save();
+      $entities[$entity->id()] = $entity;
+
+      $langcode = $entity->language()->getId();
+      $selection[$entity->id()][$langcode] = $langcode;
+    }
+    // Add the selection to the tempstore just like DeleteAction would.
+    $tempstore = \Drupal::service('user.private_tempstore')->get('entity_delete_multiple_confirm');
+    $tempstore->set($this->account->id(), $selection);
+
+    $this->drupalGet('/entity_test_enhanced/delete');
+    $assert = $this->assertSession();
+    $assert->statusCodeEquals(200);
+    $assert->elementTextContains('css', '.page-title', 'Are you sure you want to delete these items?');
+    $delete_button = $this->getSession()->getPage()->findButton('Delete');
+    $delete_button->click();
+    $assert = $this->assertSession();
+    $assert->addressEquals('/entity_test_enhanced');
+    $assert->responseContains('Deleted 2 items.');
+
+    \Drupal::entityTypeManager()->getStorage('entity_test_enhanced')->resetCache();
+    $remaining_entities = EnhancedEntity::loadMultiple(array_keys($selection));
+    $this->assertEmpty($remaining_entities);
+  }
+
+}
diff --git a/tests/src/Kernel/DeleteActionTest.php b/tests/src/Kernel/DeleteActionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..411ced102e96a94751b69fdbc8c75c1d1c466b36
--- /dev/null
+++ b/tests/src/Kernel/DeleteActionTest.php
@@ -0,0 +1,87 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\entity\Kernel\DeleteActionTest.
+ */
+
+namespace Drupal\Tests\entity\Kernel;
+
+use Drupal\entity\Plugin\Action\DeleteAction;
+use Drupal\entity_module_test\Entity\EnhancedEntity;
+use Drupal\entity_module_test\Entity\EnhancedEntityBundle;
+use Drupal\system\Entity\Action;
+use Drupal\user\Entity\User;
+use Drupal\KernelTests\KernelTestBase;
+
+/**
+ * Tests the delete entity action.
+ */
+class DeleteActionTest extends KernelTestBase {
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\user\UserInterface
+   */
+  protected $user;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['action', 'node', 'entity_module_test', 'entity',
+                            'user', 'system'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('entity_test_enhanced');
+    $this->installSchema('system', ['key_value_expire', 'sequences']);
+
+    $bundle = EnhancedEntityBundle::create([
+      'id' => 'default',
+      'label' => 'Default',
+    ]);
+    $bundle->save();
+
+    $this->user = User::create([
+      'name' => 'username',
+      'status' => 1,
+    ]);
+    $this->user->save();
+    \Drupal::service('current_user')->setAccount($this->user);
+  }
+
+  public function testAction() {
+    /** @var \Drupal\system\ActionConfigEntityInterface $action */
+    $action = Action::create([
+      'id' => 'enhanced_entity_delete_action',
+      'label' => 'Delete enhanced entity',
+      'plugin' => 'entity_delete_action:entity_test_enhanced',
+    ]);
+    $status = $action->save();
+    $this->assertEquals(SAVED_NEW, $status);
+    $this->assertInstanceOf(DeleteAction::class, $action->getPlugin());
+
+    $entities = [];
+    for ($i = 0; $i < 2; $i++) {
+      $entity = EnhancedEntity::create([
+        'type' => 'default',
+      ]);
+      $entity->save();
+      $entities[$entity->id()] = $entity;
+    }
+
+    $action->execute($entities);
+    // Confirm that the entity ids and langcodes are now in the tempstore.
+    $tempstore = \Drupal::service('user.private_tempstore')->get('entity_delete_multiple_confirm');
+    $selection = $tempstore->get($this->user->id());
+    $this->assertEquals(array_keys($entities), array_keys($selection));
+    $this->assertEquals([['en' => 'en'], ['en' => 'en']], array_values($selection));
+  }
+
+}