diff --git a/core/lib/Drupal/Core/Config/ConfigManager.php b/core/lib/Drupal/Core/Config/ConfigManager.php
index 7b3a74b..c7796c4 100644
--- a/core/lib/Drupal/Core/Config/ConfigManager.php
+++ b/core/lib/Drupal/Core/Config/ConfigManager.php
@@ -413,12 +413,12 @@ protected function callOnDependencyRemoval(ConfigEntityInterface $entity, array
       if ($type == 'config' || $type == 'content') {
         $affected_dependencies[$type] = array_map(function ($name) use ($type) {
           if ($type == 'config') {
-            $entity_type_id = $this->getEntityTypeIdByName($name);
+            return $this->loadConfigEntityByName($name);
           }
           else {
             list($entity_type_id) = explode(':', $name);
+            return $this->entityManager->loadEntityByConfigTarget($entity_type_id, $name);
           }
-          return $this->entityManager->loadEntityByConfigTarget($entity_type_id, $name);
         }, $affected_dependencies[$type]);
       }
     }
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigDependencyDeleteForm.php b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyDeleteForm.php
new file mode 100644
index 0000000..7630413
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigDependencyDeleteForm.php
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Config\Entity\ConfigDependencyDeleteForm;
+ */
+
+
+namespace Drupal\Core\Config\Entity;
+
+use Drupal\Core\Entity\EntityManagerInterface;
+
+/**
+ * Lists affected configuration entities during a during a dependency removal.
+ *
+ * This trait relies on the StringTranslationTrait.
+ */
+trait ConfigDependencyDeleteForm {
+
+  /**
+   * Translates a string to the current language or to a given language.
+   *
+   * Provided by \Drupal\Core\StringTranslation\StringTranslationTrait.
+   */
+  abstract protected function t($string, array $args = array(), array $options = array());
+
+  /**
+   * Adds form elements to list affected configuration entities.
+   *
+   * @param array $form
+   *   The form array to add elements to.
+   * @param array $dependent_entities
+   *   The list of dependent entities from
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   */
+  protected function addDependencyListsToForm(array &$form, array $dependent_entities, EntityManagerInterface $entity_manager) {
+    // Get the dependent entities.
+    $entity_types = array();
+
+    $form['entity_updates'] = array(
+      '#type' => 'details',
+      '#title' => $this->t('Configuration updates'),
+      '#description' => $this->t('The listed configuration will be updated.'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#access' => FALSE,
+    );
+
+    foreach ($dependent_entities['update'] as $entity) {
+      /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface  $entity */
+      $entity_type_id = $entity->getEntityTypeId();
+      if (!isset($form['entity_updates'][$entity_type_id])) {
+        $entity_type = $entity_manager->getDefinition($entity_type_id);
+        // Store the ID and label to sort the entity types and entities later.
+        $label = $entity_type->getLabel();
+        $entity_types[$entity_type_id] = $label;
+        $form['entity_updates'][$entity_type_id] = array(
+          '#theme' => 'item_list',
+          '#title' => $label,
+          '#items' => array(),
+        );
+      }
+      $form['entity_updates'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
+    }
+    if (!empty($dependent_entities['update'])) {
+      $form['entity_updates']['#access'] = TRUE;
+
+      // Add a weight key to the entity type sections.
+      asort($entity_types, SORT_FLAG_CASE);
+      $weight = 0;
+      foreach ($entity_types as $entity_type_id => $label) {
+        $form['entity_updates'][$entity_type_id]['#weight'] = $weight;
+        // Sort the list of entity labels alphabetically.
+        sort($form['entity_updates'][$entity_type_id]['#items'], SORT_FLAG_CASE);
+        $weight++;
+      }
+    }
+
+    $form['entity_deletes'] = array(
+      '#type' => 'details',
+      '#title' => $this->t('Configuration deletions'),
+      '#description' => $this->t('The listed configuration will be deleted.'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#access' => FALSE,
+    );
+
+    foreach ($dependent_entities['delete'] as $entity) {
+      $entity_type_id = $entity->getEntityTypeId();
+      if (!isset($form['entity_deletes'][$entity_type_id])) {
+        $entity_type = $entity_manager->getDefinition($entity_type_id);
+        // Store the ID and label to sort the entity types and entities later.
+        $label = $entity_type->getLabel();
+        $entity_types[$entity_type_id] = $label;
+        $form['entity_deletes'][$entity_type_id] = array(
+          '#theme' => 'item_list',
+          '#title' => $label,
+          '#items' => array(),
+        );
+      }
+      $form['entity_deletes'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
+    }
+    if (!empty($dependent_entities['delete'])) {
+      $form['entity_deletes']['#access'] = TRUE;
+
+      // Add a weight key to the entity type sections.
+      asort($entity_types, SORT_FLAG_CASE);
+      $weight = 0;
+      foreach ($entity_types as $entity_type_id => $label) {
+        $form['entity_deletes'][$entity_type_id]['#weight'] = $weight;
+        // Sort the list of entity labels alphabetically.
+        sort($form['entity_deletes'][$entity_type_id]['#items'], SORT_FLAG_CASE);
+        $weight++;
+      }
+    }
+
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
index 7d684e0..bb170f5 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Config\ConfigException;
 use Drupal\Core\Config\Schema\SchemaIncompleteException;
 use Drupal\Core\Entity\Entity;
 use Drupal\Core\Config\ConfigDuplicateUUIDException;
@@ -517,4 +518,35 @@ public function getThirdPartyProviders() {
     return array_keys($this->third_party_settings);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function preDelete(EntityStorageInterface $storage, array $entities) {
+    foreach ($entities as $entity) {
+      if ($entity->isUninstalling() || $entity->isSyncing()) {
+        // During extension uninstall and configuration synchronization
+        // deletions are already managed.
+        break;
+      }
+      $dependencies_for_removal = [
+        'config' => [$entity],
+        'content' => [],
+        'module' => [],
+        'theme' => []
+      ];
+      // Fix or remove any dependencies.
+      while ($dependents = \Drupal::service('config.manager')->findConfigEntityDependentsAsEntities('config', [$entity->getConfigDependencyName()])) {
+        $dependent = reset($dependents);
+        if ($dependent->onDependencyRemoval($dependencies_for_removal)) {
+          $dependent->save();
+        }
+        else {
+          $dependent->delete();
+        }
+      }
+    }
+
+    parent::preDelete($storage, $entities);
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
index 1db3b42..86095c7 100644
--- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
+++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityInterface.php
@@ -165,10 +165,6 @@ public function calculateDependencies();
    * caller for the changes to take effect. Implementations should not save the
    * entity.
    *
-   * @todo https://www.drupal.org/node/2336727 this method is only fired during
-   *   extension uninstallation but it could be used during config entity
-   *   deletion too.
-   *
    * @param array $dependencies
    *   An array of dependencies that will be deleted keyed by dependency type.
    *   Dependency types are, for example, entity, module and theme.
@@ -176,7 +172,11 @@ public function calculateDependencies();
    * @return bool
    *   TRUE if the entity has changed, FALSE if not.
    *
+   * @return bool
+   *   TRUE if the entity has been changed as a result, FALSE if not.
+   *
    * @see \Drupal\Core\Config\Entity\ConfigDependencyManager
+   * @see \Drupal\Core\Config\ConfigEntityBase::preDelete()
    * @see \Drupal\Core\Config\ConfigManager::uninstall()
    * @see \Drupal\Core\Entity\EntityDisplayBase::onDependencyRemoval()
    */
diff --git a/core/lib/Drupal/Core/Entity/EntityDeleteForm.php b/core/lib/Drupal/Core/Entity/EntityDeleteForm.php
index 71560a2..76aa3cf 100644
--- a/core/lib/Drupal/Core/Entity/EntityDeleteForm.php
+++ b/core/lib/Drupal/Core/Entity/EntityDeleteForm.php
@@ -6,6 +6,8 @@
  */
 
 namespace Drupal\Core\Entity;
+use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Form\FormStateInterface;
 
 /**
  * Provides a generic base class for an entity deletion form.
@@ -13,7 +15,26 @@
  * @ingroup entity_api
  */
 class EntityDeleteForm extends EntityConfirmFormBase {
-
   use EntityDeleteFormTrait;
 
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form = parent::buildForm($form, $form_state);
+    $entity = $this->getEntity();
+    // Only do dependency processing for configuration entities. Whilst it is
+    // possible for a configuration entity to be dependent on a content entity,
+    // these dependencies are soft and content delete permissions are often
+    // given to more users. This method should not make assumptions that $entity
+    // is a configuration entity in case we decide to remove the following
+    // condition.
+    if (!($entity instanceof ConfigEntityInterface)) {
+      return $form;
+    }
+    $dependent_entities = \Drupal::service('config.manager')->getConfigEntitiesToChangeOnDependencyRemoval($entity->getConfigDependencyKey(), [$entity->getConfigDependencyName()]);
+    $this->addDependencyListsToForm($form, $dependent_entities, $this->entityManager);
+
+    return $form;
+  }
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php b/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php
index 80bb50d..c14cb75 100644
--- a/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php
+++ b/core/lib/Drupal/Core/Entity/EntityDeleteFormTrait.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Entity;
 
+use Drupal\Core\Config\Entity\ConfigDependencyDeleteForm;
 use Drupal\Core\Form\FormStateInterface;
 
 /**
@@ -18,13 +19,7 @@
  * @ingroup entity_api
  */
 trait EntityDeleteFormTrait {
-
-  /**
-   * Translates a string to the current language or to a given language.
-   *
-   * Provided by \Drupal\Core\StringTranslation\StringTranslationTrait.
-   */
-  abstract protected function t($string, array $args = array(), array $options = array());
+  use ConfigDependencyDeleteForm;
 
   /**
    * Returns the entity of this form.
diff --git a/core/lib/Drupal/Core/Field/FieldConfigBase.php b/core/lib/Drupal/Core/Field/FieldConfigBase.php
index 7388b4b..026570f 100644
--- a/core/lib/Drupal/Core/Field/FieldConfigBase.php
+++ b/core/lib/Drupal/Core/Field/FieldConfigBase.php
@@ -264,6 +264,20 @@ public function calculateDependencies() {
   /**
    * {@inheritdoc}
    */
+  public function onDependencyRemoval(array $dependencies) {
+    $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
+    $definition = $field_type_manager->getDefinition($this->getType());
+    $changed = $definition['class']::onDependencyRemoval($this, $dependencies);
+    if ($changed) {
+      $this->save();
+    }
+    return $changed;
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
   public function postCreate(EntityStorageInterface $storage) {
     parent::postCreate($storage);
     // If it was not present in the $values passed to create(), (e.g. for
diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php
index b411b88..b2119e3 100644
--- a/core/lib/Drupal/Core/Field/FieldItemBase.php
+++ b/core/lib/Drupal/Core/Field/FieldItemBase.php
@@ -273,4 +273,11 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def
     return array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies) {
+    return FALSE;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Field/FieldItemInterface.php
index 1d0de29..f74b3f7 100644
--- a/core/lib/Drupal/Core/Field/FieldItemInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php
@@ -405,4 +405,20 @@ public function fieldSettingsForm(array $form, FormStateInterface $form_state);
    */
   public static function calculateDependencies(FieldDefinitionInterface $field_definition);
 
+  /**
+   * Informs the plugin that a dependency of the field will be deleted.
+   *
+   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+   *   The field definition.
+   * @param array $dependencies
+   *   An array of dependencies that will be deleted keyed by dependency type.
+   *   Dependency types are, for example, entity, module and theme.
+   *
+   * @return bool
+   *   TRUE if the field definition has been changed as a result, FALSE if not.
+   *
+   * @see \Drupal\Core\Config\ConfigEntityInterface::onDependencyRemoval()
+   */
+  public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies);
+
 }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index e03750d..10497ad 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -286,4 +286,26 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def
     return $dependencies;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public static function onDependencyRemoval(FieldDefinitionInterface $field_definition, array $dependencies) {
+    $changed = FALSE;
+    if (is_array($field_definition->default_value) && count($field_definition->default_value)) {
+      $target_entity_type = \Drupal::entityManager()->getDefinition($field_definition->getFieldStorageDefinition()->getSetting('target_type'));
+      foreach ($field_definition->default_value as $default_value) {
+        if (is_array($default_value) && isset($default_value['target_uuid'])) {
+          $entity = \Drupal::entityManager()->loadEntityByUuid($target_entity_type->id(), $default_value['target_uuid']);
+          // If the entity does not exist do not create the dependency.
+          // @see \Drupal\Core\Field\EntityReferenceFieldItemList::processDefaultValue()
+          if ($entity && in_array($entity, $dependencies[$target_entity_type->getConfigDependencyKey()])) {
+            $field_definition->default_value = [];
+            $changed = TRUE;
+          }
+        }
+      }
+    }
+    return $changed;
+  }
+
 }
diff --git a/core/modules/config/src/Tests/ConfigImporterTest.php b/core/modules/config/src/Tests/ConfigImporterTest.php
index d2c7cf0..bfef3a8 100644
--- a/core/modules/config/src/Tests/ConfigImporterTest.php
+++ b/core/modules/config/src/Tests/ConfigImporterTest.php
@@ -381,6 +381,10 @@ function testSecondaryUpdateDeletedDeleterFirst() {
 
   /**
    * Tests that secondary updates for deleted files work as expected.
+   *
+   * This test is completely hypothetical since we only support full
+   * configuration tree imports. Therefore, any configuration updates that cause
+   * secondary deletes should be reflected already in the staged configuration.
    */
   function testSecondaryUpdateDeletedDeleteeFirst() {
     $name_deleter = 'config_test.dynamic.deleter';
@@ -416,10 +420,10 @@ function testSecondaryUpdateDeletedDeleteeFirst() {
     $this->configImporter->reset()->import();
 
     $entity_storage = \Drupal::entityManager()->getStorage('config_test');
-    $deleter = $entity_storage->load('deleter');
-    $this->assertEqual($deleter->id(), 'deleter');
-    $this->assertEqual($deleter->uuid(), $values_deleter['uuid']);
-    $this->assertEqual($deleter->label(), $values_deleter['label']);
+    // Both entities are deleted. ConfigTest::postSave() causes updates of the
+    // deleter entity to delete the deletee entity. Since the deleter depends on
+    // the deletee, removing the deletee causes the deleter to be removed.
+    $this->assertFalse($entity_storage->load('deleter'));
     // @todo The deletee entity does not exist as the update worked but the
     //   entity was deleted after that. There is also no log message as this
     //   happened outside of the config importer.
diff --git a/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php b/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
index cabaf22..2203fd8 100644
--- a/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
+++ b/core/modules/entity_reference/src/Tests/EntityReferenceIntegrationTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\config\Tests\AssertConfigEntityImportTrait;
+use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\simpletest\WebTestBase;
 
@@ -152,6 +153,9 @@ public function testSupportedEntityTypesAndWidgets() {
       // Ensure that the field can be imported without change even after the
       // default value deleted.
       $referenced_entities[0]->delete();
+      // Reload the field since deleting the default value can change the field.
+      \Drupal::entityManager()->getStorage($field->getEntityTypeId())->resetCache([$field->id()]);
+      $field = FieldConfig::loadByName($this->entityType, $this->bundle, $this->fieldName);
       $this->assertConfigEntityImport($field);
 
       // Once the default value has been removed after saving the dependency
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index d8be776..e4562a3 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -246,24 +246,6 @@ function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
 }
 
 /**
- * Implements hook_entity_bundle_delete().
- *
- * This deletes the data for the field as well as the field themselves. This
- * function actually just marks the data and fields as deleted, leaving the
- * garbage collection for a separate process, because it is not always
- * possible to delete this much data in a single page request (particularly
- * since for some field types, the deletion is more than just a simple DELETE
- * query).
- */
-function field_entity_bundle_delete($entity_type, $bundle) {
-  // Get the fields on the bundle.
-  $fields = entity_load_multiple_by_properties('field_config', array('entity_type' => $entity_type, 'bundle' => $bundle));
-  foreach ($fields as $field) {
-    $field->delete();
-  }
-}
-
-/**
  * @} End of "defgroup field".
  */
 
diff --git a/core/modules/field/src/Entity/FieldConfig.php b/core/modules/field/src/Entity/FieldConfig.php
index c5b9ad5..802bc1b 100644
--- a/core/modules/field/src/Entity/FieldConfig.php
+++ b/core/modules/field/src/Entity/FieldConfig.php
@@ -182,6 +182,7 @@ public function calculateDependencies() {
   public static function preDelete(EntityStorageInterface $storage, array $fields) {
     $state = \Drupal::state();
 
+    parent::preDelete($storage, $fields);
     // Keep the field definitions in the state storage so we can use them
     // later during field_purge_batch().
     $deleted_fields = $state->get('field.field.deleted') ?: array();
@@ -222,7 +223,7 @@ public static function postDelete(EntityStorageInterface $storage, array $fields
     $storages_to_delete = array();
     foreach ($fields as $field) {
       $storage_definition = $field->getFieldStorageDefinition();
-      if (!$field->deleted && empty($field->noFieldDelete) && !$field->isUninstalling() && $storage_definition->isDeletable()) {
+      if (!$field->deleted && !$field->isUninstalling() && $storage_definition->isDeletable()) {
         // Key by field UUID to avoid deleting the same storage twice.
         $storages_to_delete[$storage_definition->uuid()] = $storage_definition;
       }
@@ -230,29 +231,6 @@ public static function postDelete(EntityStorageInterface $storage, array $fields
     if ($storages_to_delete) {
       \Drupal::entityManager()->getStorage('field_storage_config')->delete($storages_to_delete);
     }
-
-    // Cleanup entity displays.
-    $displays_to_update = array();
-    foreach ($fields as $field) {
-      if (!$field->deleted) {
-        $view_modes = \Drupal::entityManager()->getViewModeOptions($field->entity_type, TRUE);
-        foreach (array_keys($view_modes) as $mode) {
-          $displays_to_update['entity_view_display'][$field->entity_type . '.' . $field->bundle . '.' . $mode][] = $field->getName();
-        }
-        $form_modes = \Drupal::entityManager()->getFormModeOptions($field->entity_type, TRUE);
-        foreach (array_keys($form_modes) as $mode) {
-          $displays_to_update['entity_form_display'][$field->entity_type . '.' . $field->bundle . '.' . $mode][] = $field->getName();
-        }
-      }
-    }
-    foreach ($displays_to_update as $type => $ids) {
-      foreach (entity_load_multiple($type, array_keys($ids)) as $id => $display) {
-        foreach ($ids[$id] as $field_name) {
-          $display->removeComponent($field_name);
-        }
-        $display->save();
-      }
-    }
   }
 
   /**
diff --git a/core/modules/field/src/Entity/FieldStorageConfig.php b/core/modules/field/src/Entity/FieldStorageConfig.php
index ab869db..7d66b53 100644
--- a/core/modules/field/src/Entity/FieldStorageConfig.php
+++ b/core/modules/field/src/Entity/FieldStorageConfig.php
@@ -198,6 +198,13 @@ class FieldStorageConfig extends ConfigEntityBase implements FieldStorageConfigI
   protected $propertyDefinitions;
 
   /**
+   * Static flag set to prevent recursion during field deletes.
+   *
+   * @var bool
+   */
+  protected static $inDeletion = FALSE;
+
+  /**
    * Constructs a FieldStorageConfig object.
    *
    * @param array $values
@@ -374,29 +381,13 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
    */
   public static function preDelete(EntityStorageInterface $storage, array $field_storages) {
     $state = \Drupal::state();
-    $field_config_storage = \Drupal::entityManager()->getStorage('field_config');
 
-    // Delete fields first. Note: when deleting a field storage through
-    // FieldConfig::postDelete(), the fields have been deleted already, so
-    // no fields will be found here.
-    $field_ids = array();
-    foreach ($field_storages as $field_storage) {
-      if (!$field_storage->deleted) {
-        foreach ($field_storage->getBundles() as $bundle) {
-          $entity_type = $field_storage->getTargetEntityTypeId();
-          $field_name = $field_storage->getName();
-          $field_ids[] = "{$entity_type}.$bundle.{$field_name}";
-        }
-      }
-    }
-    if ($field_ids) {
-      $fields = $field_config_storage->loadMultiple($field_ids);
-      // Tag the objects to preserve recursive deletion of the field.
-      foreach ($fields as $field) {
-        $field->noFieldDelete = TRUE;
-      }
-      $field_config_storage->delete($fields);
-    }
+    // Set the static flag so that we don't delete field storages whilst
+    // deleting fields.
+    self::$inDeletion = TRUE;
+
+    // Delete or fix any configuration that is dependent, for example, fields.
+    parent::preDelete($storage, $field_storages);
 
     // Keep the field definitions in the state storage so we can use them later
     // during field_purge_batch().
@@ -424,6 +415,8 @@ public static function postDelete(EntityStorageInterface $storage, array $fields
         $field->deleted = TRUE;
       }
     }
+    // Unset static flag.
+    self::$inDeletion = FALSE;
   }
 
   /**
@@ -794,8 +787,9 @@ public static function loadByName($entity_type_id, $field_name) {
    */
   public function isDeletable() {
     // The field storage is not deleted, is configured to be removed when there
-    // are no fields and the field storage has no bundles.
-    return !$this->deleted && !$this->persist_with_no_fields && count($this->getBundles()) == 0;
+    // are no fields, the field storage has no bundles, and field storages are
+    // not in the process of being deleted.
+    return !$this->deleted && !$this->persist_with_no_fields && count($this->getBundles()) == 0 && !self::$inDeletion;
   }
 
   /**
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 5b2099e..67356be 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -238,17 +238,6 @@ function language_entity_bundle_rename($entity_type_id, $bundle_old, $bundle_new
 }
 
 /**
- * Implements hook_entity_bundle_delete().
- */
-function language_entity_bundle_delete($entity_type_id, $bundle) {
-  // Remove the content language settings associated with the bundle.
-  $settings = ContentLanguageSettings::loadByEntityTypeBundle($entity_type_id, $bundle);
-  if (!$settings->isNew()) {
-    $settings->delete();
-  }
-}
-
-/**
  * Returns the default language code assigned to an entity type and a bundle.
  *
  * @param string $entity_type
diff --git a/core/modules/system/src/Form/ModulesUninstallConfirmForm.php b/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
index d6e5b15..fe7515c 100644
--- a/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallConfirmForm.php
@@ -8,6 +8,7 @@
 namespace Drupal\system\Form;
 
 use Drupal\Core\Config\ConfigManagerInterface;
+use Drupal\Core\Config\Entity\ConfigDependencyDeleteForm;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Extension\ModuleInstallerInterface;
 use Drupal\Core\Form\ConfirmFormBase;
@@ -21,6 +22,7 @@
  * Builds a confirmation form to uninstall selected modules.
  */
 class ModulesUninstallConfirmForm extends ConfirmFormBase {
+  use ConfigDependencyDeleteForm;
 
   /**
    * The module installer service.
@@ -145,86 +147,9 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       }, $this->modules),
     );
 
-    // Get the dependent entities.
-    $entity_types = array();
+    // List the dependent entities.
     $dependent_entities = $this->configManager->getConfigEntitiesToChangeOnDependencyRemoval('module', $this->modules);
-
-    $form['entity_updates'] = array(
-      '#type' => 'details',
-      '#title' => $this->t('Configuration updates'),
-      '#description' => $this->t('The listed configuration will be updated.'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#access' => FALSE,
-    );
-
-    foreach ($dependent_entities['update'] as $entity) {
-      /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface  $entity */
-      $entity_type_id = $entity->getEntityTypeId();
-      if (!isset($form['entity_updates'][$entity_type_id])) {
-        $entity_type = $this->entityManager->getDefinition($entity_type_id);
-        // Store the ID and label to sort the entity types and entities later.
-        $label = $entity_type->getLabel();
-        $entity_types[$entity_type_id] = $label;
-        $form['entity_updates'][$entity_type_id] = array(
-          '#theme' => 'item_list',
-          '#title' => $label,
-          '#items' => array(),
-        );
-      }
-      $form['entity_updates'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
-    }
-    if (!empty($dependent_entities['update'])) {
-      $form['entity_updates']['#access'] = TRUE;
-
-      // Add a weight key to the entity type sections.
-      asort($entity_types, SORT_FLAG_CASE);
-      $weight = 0;
-      foreach ($entity_types as $entity_type_id => $label) {
-        $form['entity_updates'][$entity_type_id]['#weight'] = $weight;
-        // Sort the list of entity labels alphabetically.
-        sort($form['entity_updates'][$entity_type_id]['#items'], SORT_FLAG_CASE);
-        $weight++;
-      }
-    }
-
-    $form['entity_deletes'] = array(
-      '#type' => 'details',
-      '#title' => $this->t('Configuration deletions'),
-      '#description' => $this->t('The listed configuration will be deleted.'),
-      '#collapsible' => TRUE,
-      '#collapsed' => TRUE,
-      '#access' => FALSE,
-    );
-
-    foreach ($dependent_entities['delete'] as $entity) {
-      $entity_type_id = $entity->getEntityTypeId();
-      if (!isset($form['entity_deletes'][$entity_type_id])) {
-        $entity_type = $this->entityManager->getDefinition($entity_type_id);
-        // Store the ID and label to sort the entity types and entities later.
-        $label = $entity_type->getLabel();
-        $entity_types[$entity_type_id] = $label;
-        $form['entity_deletes'][$entity_type_id] = array(
-          '#theme' => 'item_list',
-          '#title' => $label,
-          '#items' => array(),
-        );
-      }
-      $form['entity_deletes'][$entity_type_id]['#items'][] = $entity->label() ?: $entity->id();
-    }
-    if (!empty($dependent_entities['delete'])) {
-      $form['entity_deletes']['#access'] = TRUE;
-
-      // Add a weight key to the entity type sections.
-      asort($entity_types, SORT_FLAG_CASE);
-      $weight = 0;
-      foreach ($entity_types as $entity_type_id => $label) {
-        $form['entity_deletes'][$entity_type_id]['#weight'] = $weight;
-        // Sort the list of entity labels alphabetically.
-        sort($form['entity_deletes'][$entity_type_id]['#items'], SORT_FLAG_CASE);
-        $weight++;
-      }
-    }
+    $this->addDependencyListsToForm($form, $dependent_entities, $this->entityManager);
 
     return parent::buildForm($form, $form_state);
   }
diff --git a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
index 4ed1c20..9ef8466 100644
--- a/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+++ b/core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
@@ -97,6 +97,13 @@ class ConfigEntityStorageTest extends UnitTestCase {
   protected $typedConfigManager;
 
   /**
+   * The configuration manager.
+   *
+   * @var \Drupal\Core\Config\ConfigManagerInterface
+   */
+  protected $configManager;
+
+  /**
    * {@inheritdoc}
    *
    * @covers ::__construct
@@ -160,10 +167,14 @@ protected function setUp() {
     $this->typedConfigManager->expects($this->any())
       ->method('getDefinition')
       ->will($this->returnValue(array('mapping' => array('id' => '', 'uuid' => '', 'dependencies' => ''))));
+
+    $this->configManager = $this->getMock('Drupal\Core\Config\ConfigManagerInterface');
+
     $container = new ContainerBuilder();
     $container->set('entity.manager', $this->entityManager);
     $container->set('config.typed', $this->typedConfigManager);
     $container->set('cache_tags.invalidator', $this->cacheTagsInvalidator);
+    $container->set('config.manager', $this->configManager);
     \Drupal::setContainer($container);
 
   }
