diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php
index 726d1b1..88a8015 100644
--- a/core/includes/entity.api.php
+++ b/core/includes/entity.api.php
@@ -452,6 +452,31 @@ function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDispl
 }
 
 /**
+ * Acts on an entity object about to be shown on an entity form.
+ *
+ * This can be typically used to pre-fill entity values or change the form state
+ * before the entity form is built. It is invoked just once when first building
+ * the entity form. Rebuilds will not trigger a new invocation.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity that is about to be shown on the form.
+ * @param $form_display
+ *   The current form display.
+ * @param $operation
+ *   The current operation.
+ * @param array $form_state
+ *   An associative array containing the current state of the form.
+ *
+ * @see \Drupal\Core\Entity\EntityFormController::prepareEntity()
+ */
+function hook_entity_prepare_form(\Drupal\Core\Entity\EntityInterface $entity, $form_display, $operation, array &$form_state) {
+  if ($operation == 'edit') {
+    $entity->label->value = 'Altered label';
+    $form_state['mymodule']['label_altered'] = TRUE;
+  }
+}
+
+/**
  * Alters the settings used for displaying an entity form.
  *
  * @param \Drupal\entity\Plugin\Core\Entity\EntityFormDisplay $form_display
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index d34d3f0..6337015 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -8,7 +8,9 @@
 namespace Drupal\Core\Entity;
 
 use Drupal\entity\EntityFormDisplayInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\Language;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Base class for entity form controllers.
@@ -26,6 +28,13 @@ class EntityFormController implements EntityFormControllerInterface {
   protected $operation;
 
   /**
+   * The module handler service.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
    * The entity being used by this form.
    *
    * @var \Drupal\Core\Entity\EntityInterface
@@ -35,11 +44,20 @@ class EntityFormController implements EntityFormControllerInterface {
   /**
    * Constructs an EntityFormController object.
    *
-   * @param string|null $operation
-   *   (optional) The name of the current operation, defaults to NULL.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    */
-  public function __construct($operation = NULL) {
-    $this->setOperation($operation);
+  public function __construct(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+    return new static(
+      $container->get('module_handler')
+    );
   }
 
   /**
@@ -127,7 +145,7 @@ protected function init(array &$form_state) {
     // Add the controller to the form state so it can be easily accessed by
     // module-provided form handlers there.
     $form_state['controller'] = $this;
-    $this->prepareEntity();
+    $this->prepareEntity($form_state);
 
     // @todo Allow the usage of different form modes by exposing a hook and the
     // UI for them.
@@ -448,6 +466,7 @@ public function buildEntity(array $form, array &$form_state) {
    * Implements \Drupal\Core\Entity\EntityFormControllerInterface::getEntity().
    */
   public function getEntity() {
+    // @todo Pick the proper translation object based on the form language here.
     return $this->entity;
   }
 
@@ -461,9 +480,38 @@ public function setEntity(EntityInterface $entity) {
 
   /**
    * Prepares the entity object before the form is built first.
+   *
+   * This can be used to fill in default values or alter the form state. It then
+   * invokes hook_entity_prepare_form() and hook_ENTITY_TYPE_prepare_form() on
+   * all modules.
+   *
+   * @param array $form_state
+   *   An associative array containing the current state of the form.
+   */
+  protected function prepareEntity(array &$form_state) {
+    $this->prepareInvokeAll('entity_prepare_form', $form_state);
+    $this->prepareInvokeAll($this->entity->entityType() . '_prepare_form', $form_state);
+  }
+
+  /**
+   * Invokes the specified prepare hook variant.
+   *
+   * @param string $hook
+   *   The hook variant name.
+   * @param array $form_state
+   *   An associative array containing the current state of the form.
    */
-  protected function prepareEntity() {
-    // @todo Perform common prepare operations and add a hook.
+  protected function prepareInvokeAll($hook, array &$form_state) {
+    $implementations = $this->moduleHandler->getImplementations($hook);
+    foreach ($implementations as $module) {
+      $function = $module . '_' . $hook;
+      if (function_exists($function)) {
+        // Ensure we pass an updated translation object and form display at
+        // each invocation, since they depend on form state which is alterable.
+        $args = array($this->getEntity(), $this->getFormDisplay($form_state), $this->operation, &$form_state);
+        call_user_func_array($function, $args);
+      }
+    }
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index c6561b6..648ec98 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -227,11 +227,11 @@ public function getFormController($entity_type, $operation) {
       $class = $this->getControllerClass($entity_type, 'form', $operation);
       if (in_array('Drupal\Core\Entity\EntityControllerInterface', class_implements($class))) {
         $this->controllers['form'][$operation][$entity_type] = $class::createInstance($this->container, $entity_type, $this->getDefinition($entity_type));
-        $this->controllers['form'][$operation][$entity_type]->setOperation($operation);
       }
       else {
-        $this->controllers['form'][$operation][$entity_type] = new $class($operation);
+        $this->controllers['form'][$operation][$entity_type] = new $class($this->container->get('module_handler'));
       }
+      $this->controllers['form'][$operation][$entity_type]->setOperation($operation);
     }
     return $this->controllers['form'][$operation][$entity_type];
   }
diff --git a/core/modules/action/lib/Drupal/action/ActionAddFormController.php b/core/modules/action/lib/Drupal/action/ActionAddFormController.php
index 85db8fe..56d7bbf 100644
--- a/core/modules/action/lib/Drupal/action/ActionAddFormController.php
+++ b/core/modules/action/lib/Drupal/action/ActionAddFormController.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Action\ActionManager;
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -28,13 +29,15 @@ class ActionAddFormController extends ActionFormControllerBase implements Entity
   /**
    * Constructs a new ActionAddFormController.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
    *   The action storage controller.
    * @param \Drupal\Core\Action\ActionManager $action_manager
    *   The action plugin manager.
    */
-  public function __construct(EntityStorageControllerInterface $storage_controller, ActionManager $action_manager) {
-    parent::__construct($storage_controller);
+  public function __construct(ModuleHandlerInterface $module_handler, EntityStorageControllerInterface $storage_controller, ActionManager $action_manager) {
+    parent::__construct($module_handler, $storage_controller);
 
     $this->actionManager = $action_manager;
   }
@@ -44,6 +47,7 @@ public function __construct(EntityStorageControllerInterface $storage_controller
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('plugin.manager.entity')->getStorageController($entity_type),
       $container->get('plugin.manager.action')
     );
diff --git a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php
index c5d58e6..d1a916d 100644
--- a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php
+++ b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityFormController;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Action\ConfigurableActionInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -35,11 +36,13 @@
   /**
    * Constructs a new action form.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
    *   The action storage controller.
    */
-  public function __construct(EntityStorageControllerInterface $storage_controller) {
-    parent::__construct();
+  public function __construct(ModuleHandlerInterface $module_handler, EntityStorageControllerInterface $storage_controller) {
+    parent::__construct($module_handler);
 
     $this->storageController = $storage_controller;
   }
@@ -49,6 +52,7 @@ public function __construct(EntityStorageControllerInterface $storage_controller
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('plugin.manager.entity')->getStorageController($entity_type)
     );
   }
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php
index 2457d97..777f695 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockFormController.php
@@ -24,7 +24,7 @@ class CustomBlockFormController extends EntityFormControllerNG {
    * Fills in a few default values, and then invokes hook_custom_block_prepare()
    * on all modules.
    */
-  protected function prepareEntity() {
+  protected function prepareEntity(array &$form_state) {
     $block = $this->entity;
     // Set up default values, if required.
     $block_type = entity_load('custom_block_type', $block->type->value);
@@ -35,7 +35,7 @@ protected function prepareEntity() {
     // Always use the default revision setting.
     $block->setNewRevision($block_type->revision);
 
-    module_invoke_all('custom_block_prepare', $block);
+    parent::prepareEntity($form_state);
   }
 
   /**
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php
index 9db5b1d..7e595d2 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityConfirmFormBase;
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -28,10 +29,13 @@ class CustomBlockTypeDeleteForm extends EntityConfirmFormBase implements EntityC
   /**
    * Constructs a query factory object.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
    *   The entity query object.
    */
-  public function __construct(QueryFactory $query_factory) {
+  public function __construct(ModuleHandlerInterface $module_handler, QueryFactory $query_factory) {
+    parent::__construct($module_handler);
     $this->queryFactory = $query_factory;
   }
 
@@ -40,6 +44,7 @@ public function __construct(QueryFactory $query_factory) {
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('entity.query')
     );
   }
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 3462abf..d577bd3 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -12,6 +12,7 @@
 use Drupal\Core\Template\Attribute;
 use Drupal\menu_link\Plugin\Core\Entity\MenuLink;
 use Drupal\menu_link\MenuLinkStorageController;
+use Drupal\node\NodeInterface;
 
 /**
  * Implements hook_help().
@@ -875,9 +876,9 @@ function book_node_predelete(EntityInterface $node) {
 }
 
 /**
- * Implements hook_node_prepare().
+ * Implements hook_node_prepare_form().
  */
-function book_node_prepare(EntityInterface $node) {
+function book_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
   // Prepare defaults for the add/edit form.
   if (empty($node->book) && (user_access('add content to books') || user_access('administer book outlines'))) {
     $node->book = array();
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index a7e43cb..85e7569 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -13,6 +13,7 @@
 use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
 use Drupal\file\Plugin\Core\Entity\File;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\node\NodeInterface;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -1156,9 +1157,9 @@ function comment_node_load($nodes, $types) {
 }
 
 /**
- * Implements hook_node_prepare().
+ * Implements hook_node_prepare_form().
  */
-function comment_node_prepare(EntityInterface $node) {
+function comment_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
   if (!isset($node->comment)) {
     $node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN);
   }
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index c0c3535..ecfceb6 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -1040,3 +1040,17 @@ function content_translation_save_settings($settings) {
   entity_info_cache_clear();
   menu_router_rebuild();
 }
+
+/**
+ * Implements hook_entity_prepare_form().
+ */
+function content_translation_entity_prepare_form(EntityInterface $entity, $form_display, $operation, array &$form_state) {
+  $target = Drupal::request()->get('content_translation_target');
+  $source = Drupal::request()->get('content_translation_source');
+  if ($target) {
+    $form_state['content_translation']['target'] = $target;
+  }
+  if ($source) {
+    $form_state['content_translation']['source'] = $source;
+  }
+}
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index e4ef836..d2c35db 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -1147,9 +1147,9 @@ function datetime_form_node_form_alter(&$form, &$form_state, $form_id) {
 }
 
 /**
- * Implements hook_node_prepare().
+ * Implements hook_node_prepare_form().
  */
-function datetime_node_prepare(NodeInterface $node) {
+function datetime_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
   // Prepare the 'Authored on' date to use datetime.
   $node->date = new DrupalDateTime($node->created);
 }
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php
index 481cf7c..a3ffe5d 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityConfirmFormBase;
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -27,10 +28,13 @@ class FieldDeleteForm extends EntityConfirmFormBase implements EntityControllerI
   /**
    * Constructs a new FieldDeleteForm object.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Entity\EntityManager $entity_manager
    *   The entity manager.
    */
-  public function __construct(EntityManager $entity_manager) {
+  public function __construct(ModuleHandlerInterface $module_handler, EntityManager $entity_manager) {
+    parent::__construct($module_handler);
     $this->entityManager = $entity_manager;
   }
 
@@ -39,6 +43,7 @@ public function __construct(EntityManager $entity_manager) {
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('plugin.manager.entity')
     );
   }
diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php b/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php
index f9d4965..98495d5 100644
--- a/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php
+++ b/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityFormController;
 use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -35,12 +36,15 @@
   /**
    * Constructs a new FilterFormatFormControllerBase.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
    *   The config factory.
    * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
    *   The entity query factory.
    */
-  public function __construct(ConfigFactory $config_factory, QueryFactory $query_factory) {
+  public function __construct(ModuleHandlerInterface $module_handler, ConfigFactory $config_factory, QueryFactory $query_factory) {
+    parent::__construct($module_handler);
     $this->configFactory = $config_factory;
     $this->queryFactory = $query_factory;
   }
@@ -50,6 +54,7 @@ public function __construct(ConfigFactory $config_factory, QueryFactory $query_f
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('config.factory'),
       $container->get('entity.query')
     );
diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php
index 60129fa..f605d0a 100644
--- a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php
+++ b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\EntityConfirmFormBase;
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -35,12 +36,15 @@ class MenuDeleteForm extends EntityConfirmFormBase implements EntityControllerIn
   /**
    * Constructs a new MenuDeleteForm.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage_controller
    *   The menu link storage controller.
    * @param \Drupal\Core\Database\Connection $connection
    *   The database connection.
    */
-  public function __construct(EntityStorageControllerInterface $storage_controller, Connection $connection) {
+  public function __construct(ModuleHandlerInterface $module_handler, EntityStorageControllerInterface $storage_controller, Connection $connection) {
+    parent::__construct($module_handler);
     $this->storageController = $storage_controller;
     $this->connection = $connection;
   }
@@ -50,6 +54,7 @@ public function __construct(EntityStorageControllerInterface $storage_controller
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('plugin.manager.entity')->getStorageController('menu_link'),
       $container->get('database')
     );
diff --git a/core/modules/menu/lib/Drupal/menu/MenuFormController.php b/core/modules/menu/lib/Drupal/menu/MenuFormController.php
index 62a92ff..a709d2e 100644
--- a/core/modules/menu/lib/Drupal/menu/MenuFormController.php
+++ b/core/modules/menu/lib/Drupal/menu/MenuFormController.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\Entity\EntityControllerInterface;
 use Drupal\Core\Entity\EntityFormController;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\Language;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -19,37 +18,6 @@
 class MenuFormController extends EntityFormController implements EntityControllerInterface {
 
   /**
-   * The module handler to invoke hooks on.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) {
-    return new static(
-      $operation,
-      $container->get('module_handler')
-    );
-  }
-
-  /**
-   * Constructs a new EntityListController object.
-   *
-   * @param string $operation
-   *   The name of the current operation.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
-   */
-  public function __construct($operation, ModuleHandlerInterface $module_handler) {
-    parent::__construct($operation);
-
-    $this->moduleHandler = $module_handler;
-  }
-
-  /**
    * Overrides Drupal\Core\Entity\EntityFormController::form().
    */
   public function form(array $form, array &$form_state) {
diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module
index 18b0ee5..f3dd6c2 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -17,6 +17,7 @@
 use Symfony\Component\HttpFoundation\JsonResponse;
 use Drupal\menu_link\Plugin\Core\Entity\MenuLink;
 use Drupal\menu_link\MenuLinkStorageController;
+use Drupal\node\NodeInterface;
 
 /**
  * Maximum length of menu name as entered by the user. Database length is 32
@@ -490,9 +491,9 @@ function menu_node_predelete(EntityInterface $node) {
 }
 
 /**
- * Implements hook_node_prepare().
+ * Implements hook_node_prepare_form().
  */
-function menu_node_prepare(EntityInterface $node) {
+function menu_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
   if (empty($node->menu)) {
     // Prepare the node for the edit form so that $node->menu always exists.
     $menu_name = strtok(variable_get('menu_parent_' . $node->type, 'main:0'), ':');
diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
index b6d3f75..6064108 100644
--- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
+++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
@@ -43,34 +43,29 @@ class MenuLinkFormController extends EntityFormController implements EntityContr
   protected $urlGenerator;
 
   /**
-   * The module handler
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
    * Constructs a new MenuLinkFormController object.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Path\AliasManagerInterface $path_alias_manager
    *   The path alias manager.
    */
-  public function __construct(MenuLinkStorageControllerInterface $menu_link_storage_controller, AliasManagerInterface $path_alias_manager, UrlGenerator $url_generator, ModuleHandlerInterface $module_handler) {
+  public function __construct(ModuleHandlerInterface $module_handler, MenuLinkStorageControllerInterface $menu_link_storage_controller, AliasManagerInterface $path_alias_manager, UrlGenerator $url_generator) {
+    parent::__construct($module_handler);
     $this->menuLinkStorageController = $menu_link_storage_controller;
     $this->pathAliasManager = $path_alias_manager;
     $this->urlGenerator = $url_generator;
-    $this->moduleHandler = $module_handler;
   }
 
   /**
    * {@inheritdoc}
    */
-  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) {
     return new static(
+      $container->get('module_handler'),
       $container->get('plugin.manager.entity')->getStorageController('menu_link'),
       $container->get('path.alias_manager.cached'),
-      $container->get('url_generator'),
-      $container->get('module_handler')
+      $container->get('url_generator')
     );
   }
 
diff --git a/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php b/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php
index 23973c9..d159b3d 100644
--- a/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php
+++ b/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\EntityConfirmFormBase;
 use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Database\Connection;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -28,10 +29,13 @@ class NodeTypeDeleteConfirm extends EntityConfirmFormBase implements EntityContr
   /**
    * Constructs a new NodeTypeDeleteConfirm object.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\Core\Database\Connection $database
    *   The database connection.
    */
-  public function __construct(Connection $database) {
+  public function __construct(ModuleHandlerInterface $module_handler, Connection $database) {
+    parent::__construct($module_handler);
     $this->database = $database;
   }
 
@@ -40,6 +44,7 @@ public function __construct(Connection $database) {
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('database')
     );
   }
diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php
index 2c362b6..03953c9 100644
--- a/core/modules/node/lib/Drupal/node/NodeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeFormController.php
@@ -25,14 +25,9 @@ class NodeFormController extends EntityFormController {
   protected $settings;
 
   /**
-   * Prepares the node object.
-   *
-   * Fills in a few default values, and then invokes hook_node_prepare() on all
-   * modules.
-   *
-   * Overrides Drupal\Core\Entity\EntityFormController::prepareEntity().
+   * {@inheritdoc}
    */
-  protected function prepareEntity() {
+  protected function prepareEntity(array &$form_state) {
     $node = $this->entity;
     // Set up default values, if required.
     $type = entity_load('node_type', $node->bundle());
@@ -63,7 +58,7 @@ protected function prepareEntity() {
     // Always use the default revision setting.
     $node->setNewRevision(in_array('revision', $this->settings['options']));
 
-    module_invoke_all('node_prepare', $node);
+    parent::prepareEntity($form_state);
   }
 
   /**
diff --git a/core/modules/node/lib/Drupal/node/NodeTypeFormController.php b/core/modules/node/lib/Drupal/node/NodeTypeFormController.php
index aaa287b..ec465e1 100644
--- a/core/modules/node/lib/Drupal/node/NodeTypeFormController.php
+++ b/core/modules/node/lib/Drupal/node/NodeTypeFormController.php
@@ -10,7 +10,6 @@
 use Drupal\Core\Entity\EntityFormController;
 use Drupal\Core\Entity\EntityControllerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 
 /**
  * Form controller for node type forms.
@@ -18,36 +17,6 @@
 class NodeTypeFormController extends EntityFormController implements EntityControllerInterface {
 
   /**
-   * The module handler service.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
-   * Constructs a NodeTypeFormController object.
-   *
-   * @param string $operation
-   *   The name of the current operation.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   The module handler to invoke hooks on.
-   */
-  public function __construct($operation, ModuleHandlerInterface $module_handler) {
-    parent::__construct($operation);
-    $this->moduleHandler = $module_handler;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) {
-    return new static(
-      $operation,
-      $container->get('module_handler')
-    );
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function form(array $form, array &$form_state) {
diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php
index 3e0cf3c..51abca3 100644
--- a/core/modules/node/node.api.php
+++ b/core/modules/node/node.api.php
@@ -94,7 +94,8 @@
  *   - field_attach_delete_revision()
  * - Preparing a node for editing (calling node_form() - note that if it is an
  *   existing node, it will already be loaded; see the Loading section above):
- *   - hook_node_prepare() (all)
+ *   - hook_node_prepare_form() (all)
+ *   - hook_entity_prepare_form() (all)
  *   - field_attach_form()
  * - Validating a node during editing form submit (calling
  *   node_form_validate()):
@@ -598,12 +599,18 @@ function hook_node_access($node, $op, $account, $langcode) {
  *
  * This hook is invoked from NodeFormController::prepareEntity().
  *
- * @param \Drupal\Core\Entity\EntityInterface $node
- *   The node that is about to be shown on the add/edit form.
+ * @param \Drupal\node\NodeInterface $node
+ *   The node that is about to be shown on the form.
+ * @param $form_display
+ *   The current form display.
+ * @param $operation
+ *   The current operation.
+ * @param array $form_state
+ *   An associative array containing the current state of the form.
  *
  * @ingroup node_api_hooks
  */
-function hook_node_prepare(\Drupal\Core\Entity\EntityInterface $node) {
+function hook_node_prepare_form(\Drupal\node\NodeInterface $node, $form_display, $operation, array &$form_state) {
   if (!isset($node->comment)) {
     $node->comment = variable_get("comment_$node->type", COMMENT_NODE_OPEN);
   }
diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php b/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php
index 296ae9b..aec4a4e 100644
--- a/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php
+++ b/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php
@@ -9,10 +9,10 @@
 
 use Drupal\Core\Entity\EntityConfirmFormBase;
 use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\shortcut\ShortcutStorageControllerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Database\Connection;
-use Drupal\Core\Extension\ModuleHandlerInterface;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -28,13 +28,6 @@ class ShortcutDeleteForm extends EntityConfirmFormBase implements EntityControll
   protected $database;
 
   /**
-   * The module handler service.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
-  /**
    * The shortcut storage controller.
    *
    * @var \Drupal\shortcut\ShortcutStorageControllerInterface
@@ -44,9 +37,9 @@ class ShortcutDeleteForm extends EntityConfirmFormBase implements EntityControll
   /**
    * Constructs a ShortcutDeleteForm object.
    */
-  public function __construct(Connection $database, ModuleHandlerInterface $module_handler, ShortcutStorageControllerInterface $storage_controller) {
+  public function __construct(ModuleHandlerInterface $module_handler, Connection $database, ShortcutStorageControllerInterface $storage_controller) {
+    parent::__construct($module_handler);
     $this->database = $database;
-    $this->moduleHandler = $module_handler;
     $this->storageController = $storage_controller;
   }
 
@@ -55,8 +48,8 @@ public function __construct(Connection $database, ModuleHandlerInterface $module
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
-      $container->get('database'),
       $container->get('module_handler'),
+      $container->get('database'),
       $container->get('plugin.manager.entity')->getStorageController('shortcut')
     );
   }
diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module
index 2d50934..9c88847 100644
--- a/core/modules/translation/translation.module
+++ b/core/modules/translation/translation.module
@@ -20,8 +20,10 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityFormControllerInterface;
 use Drupal\Core\Language\Language;
 use Drupal\entity\Plugin\Core\Entity\EntityDisplay;
+use Drupal\node\NodeInterface;
 
 /**
  * Implements hook_help().
@@ -304,9 +306,9 @@ function translation_node_view(EntityInterface $node, EntityDisplay $display, $v
 }
 
 /**
- * Implements hook_node_prepare().
+ * Implements hook_node_prepare_form().
  */
-function translation_node_prepare(EntityInterface $node) {
+function translation_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
   $query = Drupal::request()->query;
   $translation = $query->get('translation');
   $target = $query->get('target');
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php
index 53920b4..97b9b88 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php
@@ -8,6 +8,7 @@
 namespace Drupal\views_ui;
 
 use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\views\Plugin\views\wizard\WizardPluginBase;
 use Drupal\views\Plugin\views\wizard\WizardException;
 use Drupal\views\Plugin\ViewsPluginManager;
@@ -28,10 +29,14 @@ class ViewAddFormController extends ViewFormControllerBase implements EntityCont
   /**
    * Constructs a new ViewEditFormController object.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\views\Plugin\ViewsPluginManager $wizard_manager
    *   The wizard plugin manager.
    */
-  public function __construct(ViewsPluginManager $wizard_manager) {
+  public function __construct(ModuleHandlerInterface $module_handler, ViewsPluginManager $wizard_manager) {
+    parent::__construct($module_handler);
+
     $this->wizardManager = $wizard_manager;
   }
 
@@ -40,6 +45,7 @@ public function __construct(ViewsPluginManager $wizard_manager) {
    */
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
+      $container->get('module_handler'),
       $container->get('plugin.manager.views.wizard')
     );
   }
@@ -56,7 +62,7 @@ public function init(array &$form_state) {
   /**
    * Overrides Drupal\Core\Entity\EntityFormController::prepareForm().
    */
-  protected function prepareEntity() {
+  protected function prepareEntity(array &$form_state) {
     // Do not prepare the entity while it is being added.
   }
 
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewCloneFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewCloneFormController.php
index 6f5e320..d027e31 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewCloneFormController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewCloneFormController.php
@@ -24,7 +24,7 @@ public function init(array &$form_state) {
   /**
    * Overrides \Drupal\Core\Entity\EntityFormController::prepareForm().
    */
-  protected function prepareEntity() {
+  protected function prepareEntity(array &$form_state) {
     // Do not prepare the entity while it is being added.
   }
 
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
index 04dd507..e3fa4c6 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Ajax\AjaxResponse;
 use Drupal\Core\Ajax\HtmlCommand;
 use Drupal\Core\Ajax\ReplaceCommand;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\views\ViewExecutable;
 use Drupal\Core\Entity\EntityControllerInterface;
@@ -39,12 +40,16 @@ class ViewEditFormController extends ViewFormControllerBase implements EntityCon
   /**
    * Constructs a new ViewEditFormController object.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\user\TempStoreFactory $temp_store_factory
    *   The factory for the temp store object.
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request object.
    */
-  public function __construct(TempStoreFactory $temp_store_factory, Request $request) {
+  public function __construct(ModuleHandlerInterface $module_handler, TempStoreFactory $temp_store_factory, Request $request) {
+    parent::__construct($module_handler);
+
     $this->tempStore = $temp_store_factory->get('views');
     $this->request = $request;
   }
@@ -52,8 +57,9 @@ public function __construct(TempStoreFactory $temp_store_factory, Request $reque
   /**
    * {@inheritdoc}
    */
-  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) {
     return new static(
+      $container->get('module_handler'),
       $container->get('user.tempstore'),
       $container->get('request')
     );
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php
index 98637f7..87a760a 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php
@@ -41,7 +41,7 @@ public function init(array &$form_state) {
   /**
    * Overrides Drupal\Core\Entity\EntityFormController::prepareForm().
    */
-  protected function prepareEntity() {
+  protected function prepareEntity(array &$form_state) {
     // Determine the displays available for editing.
     if ($tabs = $this->getDisplayTabs($this->entity)) {
       // If a display isn't specified, use the first one.
@@ -66,6 +66,8 @@ protected function prepareEntity() {
     elseif ($this->displayID) {
       throw new NotFoundHttpException();
     }
+
+    parent::prepareEntity($form_state);
   }
 
   /**
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php
index 555ebac..d47d869 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php
@@ -8,6 +8,7 @@
 namespace Drupal\views_ui;
 
 use Drupal\Core\Entity\EntityControllerInterface;
+use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\user\TempStoreFactory;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -26,18 +27,23 @@ class ViewPreviewFormController extends ViewFormControllerBase implements Entity
   /**
    * Constructs a new ViewPreviewFormController object.
    *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler service.
    * @param \Drupal\user\TempStoreFactory $temp_store_factory
    *   The factory for the temp store object.
    */
-  public function __construct(TempStoreFactory $temp_store_factory) {
+  public function __construct(ModuleHandlerInterface $module_handler, TempStoreFactory $temp_store_factory) {
+    parent::__construct($module_handler);
+
     $this->tempStore = $temp_store_factory->get('views');
   }
 
   /**
    * {@inheritdoc}
    */
-  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
+  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) {
     return new static(
+      $container->get('module_handler'),
       $container->get('user.tempstore')
     );
   }
