diff --git a/core/core.services.yml b/core/core.services.yml
index bd0464c45a516c4b5bd7594104ee11455e8fa1e6..12f3a3c8a0711b4602efe40c791640b9c6e00102 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -218,7 +218,7 @@ services:
     arguments: ['@event_dispatcher', '@service_container', '@controller_resolver']
   language_manager:
     class: Drupal\Core\Language\LanguageManager
-    arguments: ['@state', '@module_handler']
+    arguments: ['@state']
   string_translator.custom_strings:
     class: Drupal\Core\StringTranslation\Translator\CustomStrings
     arguments: ['@settings']
diff --git a/core/includes/language.inc b/core/includes/language.inc
index 07cc38354215dea8c51b95ca26391362f47760e4..e057616c23f30b444e37fedb2f013e2cf3b33b0f 100644
--- a/core/includes/language.inc
+++ b/core/includes/language.inc
@@ -545,6 +545,30 @@ function language_url_split_prefix($path, $languages) {
   return array(FALSE, $path);
 }
 
+/**
+ * Returns the possible fallback languages ordered by language weight.
+ *
+ * @param
+ *   (optional) The language type. Defaults to Language::TYPE_CONTENT.
+ *
+ * @return
+ *   An array of language codes.
+ */
+function language_fallback_get_candidates($type = Language::TYPE_CONTENT) {
+  $fallback_candidates = &drupal_static(__FUNCTION__);
+
+  if (!isset($fallback_candidates)) {
+    // Get languages ordered by weight, add Language::LANGCODE_NOT_SPECIFIED at the end.
+    $fallback_candidates = array_keys(language_list());
+    $fallback_candidates[] = Language::LANGCODE_NOT_SPECIFIED;
+
+    // Let other modules hook in and add/change candidates.
+    drupal_alter('language_fallback_candidates', $fallback_candidates);
+  }
+
+  return $fallback_candidates;
+}
+
 /**
  * @} End of "language_negotiation"
  */
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 5447e90a3fec792fd81294b329f1236f56b84f7f..177a4952ca6cdc0eb283b765423c7a924f4870b2 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -423,12 +423,6 @@ protected function getTranslatedField($property_name, $langcode) {
    */
   public function set($property_name, $value, $notify = TRUE) {
     $this->get($property_name)->setValue($value, FALSE);
-
-    if ($property_name == 'langcode') {
-      // Avoid using unset as this unnecessarily triggers magic methods later
-      // on.
-      $this->language = NULL;
-    }
   }
 
   /**
@@ -664,7 +658,6 @@ protected function initializeTranslation($langcode) {
     $translation->values = &$this->values;
     $translation->fields = &$this->fields;
     $translation->translations = &$this->translations;
-    $translation->enforceIsNew = &$this->enforceIsNew;
     $translation->translationInitialize = FALSE;
 
     return $translation;
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityFormController.php b/core/lib/Drupal/Core/Entity/ContentEntityFormController.php
index 7f613bc85078b0a2f56e7cb2fb312d9970e48caa..2103fc2b938cb51152e042cf37e223096a128a9c 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityFormController.php
@@ -8,7 +8,6 @@
 namespace Drupal\Core\Entity;
 
 use Drupal\Core\Language\Language;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Entity form controller variant for content entity types.
@@ -17,32 +16,6 @@
  */
 class ContentEntityFormController extends EntityFormController {
 
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a ContentEntityFormController object.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   */
-  public function __construct(EntityManagerInterface $entity_manager) {
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('entity.manager')
-    );
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -65,7 +38,6 @@ public function form(array $form, array &$form_state) {
    * {@inheritdoc}
    */
   public function validate(array $form, array &$form_state) {
-    $this->updateFormLangcode($form_state);
     $entity = $this->buildEntity($form, $form_state);
     $entity_type = $entity->entityType();
     $entity_langcode = $entity->language()->id;
@@ -101,22 +73,53 @@ public function validate(array $form, array &$form_state) {
   protected function init(array &$form_state) {
     // Ensure we act on the translation object corresponding to the current form
     // language.
-    $langcode = $this->getFormLangcode($form_state);
-    $this->entity = $this->entity->getTranslation($langcode);
+    $this->entity = $this->getTranslatedEntity($form_state);
     parent::init($form_state);
   }
 
+  /**
+   * Returns the translation object corresponding to the form language.
+   *
+   * @param array $form_state
+   *   A keyed array containing the current state of the form.
+   */
+  protected function getTranslatedEntity(array $form_state) {
+    $langcode = $this->getFormLangcode($form_state);
+    $translation = $this->entity->getTranslation($langcode);
+    // Ensure that the entity object is a BC entity if the original one is.
+    return $this->entity instanceof EntityBCDecorator ? $translation->getBCEntity() : $translation;
+  }
+
   /**
    * {@inheritdoc}
    */
-  public function getFormLangcode(array &$form_state) {
-    if (empty($form_state['langcode'])) {
-      // Imply a 'view' operation to ensure users edit entities in the same
-      // language they are displayed. This allows to keep contextual editing
-      // working also for multilingual entities.
-      $form_state['langcode'] = $this->entityManager->getTranslationFromContext($this->entity)->language()->id;
+  public function getFormLangcode(array $form_state) {
+    $entity = $this->entity;
+    if (!empty($form_state['langcode'])) {
+      $langcode = $form_state['langcode'];
+    }
+    else {
+      // If no form langcode was provided we default to the current content
+      // language and inspect existing translations to find a valid fallback,
+      // if any.
+      $translations = $entity->getTranslationLanguages();
+      $languageManager = \Drupal::languageManager();
+      $langcode = $languageManager->getLanguage(Language::TYPE_CONTENT)->id;
+      $fallback = $languageManager->isMultilingual() ? language_fallback_get_candidates() : array();
+      while (!empty($langcode) && !isset($translations[$langcode])) {
+        $langcode = array_shift($fallback);
+      }
+    }
+
+    // If the site is not multilingual or no translation for the given form
+    // language is available, fall back to the entity language.
+    if (!empty($langcode))  {
+      return $langcode;
+    }
+    else {
+      // If the entity is translatable, return the original language.
+      return $entity->getUntranslated()->language()->id;
     }
-    return $form_state['langcode'];
   }
 
   /**
@@ -133,8 +136,8 @@ public function buildEntity(array $form, array &$form_state) {
     $entity = clone $this->entity;
     $entity_type = $entity->entityType();
     $info = entity_get_info($entity_type);
+    // @todo Exploit the Field API to process the submitted entity fields.
 
-    // @todo Exploit the Entity Field API to process the submitted field values.
     // Copy top-level form values that are entity fields but not handled by
     // field API without changing existing entity fields that are not being
     // edited by this form. Values of fields handled by field API are copied
@@ -160,5 +163,4 @@ public function buildEntity(array $form, array &$form_state) {
     }
     return $entity;
   }
-
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index 54ee489a70308af096cdfafe4e128213aa94d82b..52ac7d54389b5fc81654babd1002577a9e40cb21 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -269,7 +269,6 @@ protected function actions(array $form, array &$form_state) {
    * {@inheritdoc}
    */
   public function validate(array $form, array &$form_state) {
-    $this->updateFormLangcode($form_state);
     // @todo Remove this.
     // Execute legacy global validation handlers.
     unset($form_state['validate_handlers']);
@@ -293,6 +292,8 @@ public function validate(array $form, array &$form_state) {
   public function submit(array $form, array &$form_state) {
     // Remove button and internal Form API values from submitted values.
     form_state_values_clean($form_state);
+
+    $this->updateFormLangcode($form_state);
     $this->entity = $this->buildEntity($form, $form_state);
     return $this->entity;
   }
@@ -324,7 +325,7 @@ public function delete(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function getFormLangcode(array &$form_state) {
+  public function getFormLangcode(array $form_state) {
     return $this->entity->language()->id;
   }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php
index 6ad106bfec469c2bbf85741a7675b04f60f7d806..07d8af17b688bf1e123dd14f66cf4d55f1b2cb1d 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php
@@ -26,7 +26,7 @@ interface EntityFormControllerInterface extends BaseFormIdInterface {
    * @return string
    *   The form language code.
    */
-  public function getFormLangcode(array &$form_state);
+  public function getFormLangcode(array $form_state);
 
   /**
    * Checks whether the current form language matches the entity one.
diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php
index f02bb1e784be73ac56972332cb6c8d7394421c08..5f84ac90f105f586285732921e4653ad6757c82b 100644
--- a/core/lib/Drupal/Core/Entity/EntityInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityInterface.php
@@ -91,7 +91,7 @@ public function bundle();
    *
    * @param $langcode
    *   (optional) The language code of the language that should be used for
-   *   getting the label. If set to NULL, the entity's active language is
+   *   getting the label. If set to NULL, the entity's default language is
    *   used.
    *
    * @return
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index 5fc2d16f0983c5f7be284305c6b1c6f1558eec95..101c8b71d0aad87836a8dc6af0592683cc60ec0f 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -10,7 +10,6 @@
 use Drupal\Component\Plugin\PluginManagerBase;
 use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Component\Utility\NestedArray;
-use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Language\LanguageManager;
 use Drupal\Core\Language\Language;
@@ -18,8 +17,8 @@
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\InfoHookDecorator;
+use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
-use Drupal\Core\TypedData\TranslatableInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -457,37 +456,4 @@ public function getEntityTypeLabels() {
     return $options;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = array()) {
-    $translation = $entity;
-
-    if ($entity instanceof TranslatableInterface) {
-      if (empty($langcode)) {
-        $langcode = $this->languageManager->getLanguage(Language::TYPE_CONTENT)->id;
-      }
-
-      // Retrieve language fallback candidates to perform the entity language
-      // negotiation.
-      $context['data'] = $entity;
-      $context += array('operation' => 'entity_view');
-      $candidates = $this->languageManager->getFallbackCandidates($langcode, $context);
-
-      // Ensure the default language has the proper language code.
-      $default_language = $entity->getUntranslated()->language();
-      $candidates[$default_language->id] = Language::LANGCODE_DEFAULT;
-
-      // Return the most fitting entity translation.
-      foreach ($candidates as $candidate) {
-        if ($entity->hasTranslation($candidate)) {
-          $translation = $entity->getTranslation($candidate);
-          break;
-        }
-      }
-    }
-
-    return $translation;
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
index d561f530e602fd087f1b9d5e1625c59a0951ed77..0e898cb6d8c4f9319136d6cc6f2797bf36470992 100644
--- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
@@ -244,27 +244,4 @@ public function getForm(EntityInterface $entity, $operation = 'default', array $
    */
   public function getBundleInfo($entity_type);
 
-  /**
-   * Returns the entity translation to be used in the given context.
-   *
-   * This will check whether a translation for the desired language is available
-   * and if not, it will fall back to the most appropriate translation based on
-   * the provided context.
-   *
-   * @param \Drupal\Core\Entity\EntityInterface $entity
-   *   The entity whose translation will be returned.
-   * @param string $langcode
-   *   (optional) The language of the current context. Defaults to the current
-   *   content language.
-   * @param array $context
-   *   (optional) An associative array of arbitrary data that can be useful to
-   *   determine the proper fallback sequence.
-   *
-   * @return \Drupal\Core\Entity\EntityInterface
-   *   An entity object for the translated data.
-   *
-   * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates()
-   */
-  public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = array());
-
 }
diff --git a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
index 2680e6fd5986b51adcb44eabfa8f26084a76eff5..b79ca59b325e3ff3ef03c9f01ae11f8d42bc967b 100644
--- a/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
+++ b/core/lib/Drupal/Core/Entity/EntityViewBuilder.php
@@ -7,15 +7,13 @@
 
 namespace Drupal\Core\Entity;
 
-use Drupal\Core\Entity\EntityManager;
-use Drupal\Core\Language\Language;
 use Drupal\entity\Entity\EntityDisplay;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Language\Language;
 
 /**
  * Base class for entity view controllers.
  */
-class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderInterface {
+class EntityViewBuilder implements EntityViewBuilderInterface {
 
   /**
    * The type of entities for which this controller is instantiated.
@@ -33,13 +31,6 @@ class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderI
    */
   protected $entityInfo;
 
-  /**
-   * The entity manager service.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
   /**
    * An array of view mode info for the type of entities for which this
    * controller is instantiated.
@@ -58,30 +49,12 @@ class EntityViewBuilder implements EntityControllerInterface, EntityViewBuilderI
    */
   protected $cacheBin = 'cache';
 
-  /**
-   * Constructs a new EntityViewBuilder.
-   *
-   * @param string $entity_type
-   *   The entity type.
-   * @param array $entity_info
-   *   The entity information array.
-   * @param \Drupal\Core\Entity\EntityManager $entity_manager
-   *   The entity manager service.
-   */
-  public function __construct($entity_type, array $entity_info, EntityManager $entity_manager) {
+  public function __construct($entity_type) {
     $this->entityType = $entity_type;
-    $this->entityInfo = $entity_info;
-    $this->entityManager = $entity_manager;
+    $this->entityInfo = entity_get_info($entity_type);
     $this->viewModesInfo = entity_get_view_modes($entity_type);
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
-    return new static($entity_type, $entity_info, $container->get('entity.manager'));
-  }
-
   /**
    * {@inheritdoc}
    */
@@ -194,14 +167,9 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la
     $view_modes = array();
     $displays = array();
     $context = array('langcode' => $langcode);
-    foreach ($entities as $key => $entity) {
+    foreach ($entities as $entity) {
       $bundle = $entity->bundle();
 
-      // Ensure that from now on we are dealing with the proper translation
-      // object.
-      $entity = $this->entityManager->getTranslationFromContext($entity, $langcode);
-      $entities[$key] = $entity;
-
       // Allow modules to change the view mode.
       $entity_view_mode = $view_mode;
       drupal_alter('entity_view_mode', $entity_view_mode, $entity, $context);
diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php
index b5ea7101f392d8c7b63136579583767f36ab27e6..7181b32841a1dfb3d8a37f1fdf1bdaee718a0818 100644
--- a/core/lib/Drupal/Core/Language/Language.php
+++ b/core/lib/Drupal/Core/Language/Language.php
@@ -153,7 +153,7 @@ public function extend($obj) {
    * @param array $languages
    *   The array of language objects keyed by langcode.
    */
-  public static function sort(&$languages) {
+  public static function sort($languages) {
     uasort($languages, function ($a, $b) {
       $a_weight = isset($a->weight) ? $a->weight : 0;
       $b_weight = isset($b->weight) ? $b->weight : 0;
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
index 532d4049419eb2266646ec30d278782f090e4f0f..7bc716d34167d7d8415efdfb4fcad37d3f0e4624 100644
--- a/core/lib/Drupal/Core/Language/LanguageManager.php
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -7,10 +7,8 @@
 
 namespace Drupal\Core\Language;
 
-use Drupal\Component\Utility\MapArray;
-use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
 use Symfony\Component\HttpFoundation\Request;
+use Drupal\Core\KeyValueStore\KeyValueStoreInterface;
 
 /**
  * Class responsible for initializing each language type.
@@ -31,13 +29,6 @@ class LanguageManager {
    */
   protected $state = NULL;
 
-  /**
-   * The module handler service.
-   *
-   * @var \Drupal\Core\Extension\ModuleHandlerInterface
-   */
-  protected $moduleHandler;
-
   /**
    * An array of language objects keyed by language type.
    *
@@ -66,13 +57,10 @@ class LanguageManager {
    * Constructs an LanguageManager object.
    *
    * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state
-   *   (optional) The state keyvalue store. Defaults to NULL.
-   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
-   *   (optional) The module handler service. Defaults to NULL.
+   *   The state keyvalue store.
    */
-  public function __construct(KeyValueStoreInterface $state = NULL, ModuleHandlerInterface $module_handler = NULL) {
+  public function __construct(KeyValueStoreInterface $state = NULL) {
     $this->state = $state;
-    $this->moduleHandler = $module_handler;
   }
 
   /**
@@ -173,53 +161,6 @@ public function isMultilingual() {
     return ($this->state->get('language_count') ?: 1) > 1;
   }
 
-  /**
-   * Returns the language fallback candidates for a given context.
-   *
-   * @param string $langcode
-   *   (optional) The language of the current context. Defaults to NULL.
-   * @param array $context
-   *   (optional) An associative array of data that can be useful to determine
-   *   the fallback sequence. The following keys are used in core:
-   *   - langcode: The desired language.
-   *   - operation: The name of the operation indicating the context where
-   *     language fallback is being applied, e.g. 'entity_view'.
-   *   - data: An arbitrary data structure that makes sense in the provided
-   *     context, e.g. an entity.
-   *
-   * @return array
-   *   An array of language codes sorted by priority: first values should be
-   *   tried first.
-   */
-  public function getFallbackCandidates($langcode = NULL, array $context = array()) {
-    if ($this->isMultilingual()) {
-      // Get languages ordered by weight, add Language::LANGCODE_NOT_SPECIFIED at
-      // the end.
-      $candidates = array_keys(language_list());
-      $candidates[] = Language::LANGCODE_NOT_SPECIFIED;
-      $candidates = MapArray::copyValuesToKeys($candidates);
-
-      // The first candidate should always be the desired language if specified.
-      if (!empty($langcode)) {
-        $candidates = array($langcode => $langcode) + $candidates;
-      }
-
-      // Let other modules hook in and add/change candidates.
-      $type = 'language_fallback_candidates';
-      $types = array();
-      if (!empty($context['operation'])) {
-        $types[] = $type . '_' .  $context['operation'];
-      }
-      $types[] = $type;
-      $this->moduleHandler->alter($types, $candidates, $context);
-    }
-    else {
-      $candidates = array(Language::LANGCODE_DEFAULT);
-    }
-
-    return $candidates;
-  }
-
   /**
    * Returns an array of the available language types.
    *
diff --git a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
index af66bfee39c792a0ae5ea75a4d21826add96f0a8..f94aa0b14ee485c020057abff89fc0211b4c6524 100644
--- a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
+++ b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
@@ -7,8 +7,6 @@
 
 namespace Drupal\Core\TypedData;
 
-use Drupal\Core\Language\LanguageManager;
-
 /**
  * Interface for translatable data.
  */
@@ -37,9 +35,10 @@ public function getTranslationLanguages($include_default = TRUE);
   /**
    * Gets a translation of the data.
    *
-   * The returned translation has to be of the same type than this typed data
-   * object. If the specified translation does not exist, a new one will be
-   * instantiated.
+   * The returned translation has to be implement the same typed data interfaces
+   * as this typed data object, excluding the TranslatableInterface. E.g., if
+   * this typed data object implements the ComplexDataInterface and
+   * AccessibleInterface, the translation object has to implement both as well.
    *
    * @param $langcode
    *   The language code of the translation to get or Language::LANGCODE_DEFAULT
@@ -50,6 +49,7 @@ public function getTranslationLanguages($include_default = TRUE);
    */
   public function getTranslation($langcode);
 
+
   /**
    * Returns the translatable object referring to the original language.
    *
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php b/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php
index d4761f5eab3ca5d02840357f439ddc7566a310c9..0ca5bef07cd37266a869c9fc154e2f13e9257fb4 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/FeedFormController.php
@@ -9,7 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Entity\ContentEntityFormController;
-use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Language\Language;
 use Drupal\aggregator\CategoryStorageControllerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -19,6 +19,13 @@
  */
 class FeedFormController extends ContentEntityFormController {
 
+  /**
+   * The feed storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $feedStorageController;
+
   /**
    * The category storage controller.
    *
@@ -29,13 +36,13 @@ class FeedFormController extends ContentEntityFormController {
   /**
    * Constructs a FeedForm object.
    *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $feed_storage
+   *   The feed storage.
    * @param \Drupal\aggregator\CategoryStorageControllerInterface $category_storage_controller
    *   The category storage controller.
    */
-  public function __construct(EntityManagerInterface $entity_manager, CategoryStorageControllerInterface $category_storage_controller) {
-    parent::__construct($entity_manager);
+  public function __construct(EntityStorageControllerInterface $feed_storage, CategoryStorageControllerInterface $category_storage_controller) {
+    $this->feedStorageController = $feed_storage;
     $this->categoryStorageController = $category_storage_controller;
   }
 
@@ -44,7 +51,7 @@ public function __construct(EntityManagerInterface $entity_manager, CategoryStor
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('entity.manager'),
+      $container->get('plugin.manager.entity')->getStorageController('aggregator_feed'),
       $container->get('aggregator.category.storage')
     );
   }
@@ -118,8 +125,7 @@ public function form(array $form, array &$form_state) {
   public function validate(array $form, array &$form_state) {
     $feed = $this->buildEntity($form, $form_state);
     // Check for duplicate titles.
-    $feed_storage_controller = $this->entityManager->getStorageController('aggregator_feed');
-    $result = $feed_storage_controller->getFeedDuplicates($feed);
+    $result = $this->feedStorageController->getFeedDuplicates($feed);
     foreach ($result as $item) {
       if (strcasecmp($item->title, $feed->label()) == 0) {
         form_set_error('title', $this->t('A feed named %feed already exists. Enter a unique title.', array('%feed' => $feed->label())));
diff --git a/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php b/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php
index 61ff1fc763f0cde48aacf4d18b87d1bf68222200..94d9b8a2806a5e963c97f8cb38e34932c79d617f 100644
--- a/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php
+++ b/core/modules/book/lib/Drupal/book/Form/BookOutlineForm.php
@@ -8,7 +8,6 @@
 namespace Drupal\book\Form;
 
 use Drupal\Core\Entity\ContentEntityFormController;
-use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\book\BookManager;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -33,25 +32,19 @@ class BookOutlineForm extends ContentEntityFormController {
 
   /**
    * Constructs a BookOutlineForm object.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   * @param \Drupal\book\BookManager $book_manager
-   *   The BookManager service.
    */
-  public function __construct(EntityManagerInterface $entity_manager, BookManager $book_manager) {
-    parent::__construct($entity_manager);
-    $this->bookManager = $book_manager;
+  public function __construct(BookManager $bookManager) {
+    $this->bookManager = $bookManager;
   }
 
   /**
-   * {@inheritdoc}
+   * This method lets us inject the services this class needs.
+   *
+   * Only inject services that are actually needed. Which services
+   * are needed will vary by the controller.
    */
   public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('entity.manager'),
-      $container->get('book.manager')
-    );
+    return new static($container->get('book.manager'));
   }
 
   /**
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index f6ab885ae26191ce288c83e9ae000deaa32c0ab8..8b28e76d33195b30a27d49e8de94f5af6ece167f 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -896,7 +896,7 @@ function comment_translation_configuration_element_submit($form, &$form_state) {
   $key = 'language_configuration';
   $comment_form_state = array(
     'content_translation' => array('key' => $key),
-    'language' => array($key => array('entity_type' => 'comment', 'bundle' => $form['#field']->name)),
+    'language' => array($key => array('entity_type' => 'comment', 'bundle' => $form['#field']['name'])),
     'values' => array($key => array('content_translation' => $form_state['values']['content_translation'])),
   );
   content_translation_language_configuration_element_submit($form, $comment_form_state);
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
index f0c38ad880d32830815cf15b7682cff597d3e9d1..db10747f4aa561981b282e8c08ed34929324482d 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php
@@ -23,6 +23,13 @@
  */
 class CommentFormController extends ContentEntityFormController {
 
+  /**
+   * The entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
   /**
    * The field info service.
    *
@@ -51,28 +58,13 @@ public static function create(ContainerInterface $container) {
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
    */
+
   public function __construct(EntityManagerInterface $entity_manager, FieldInfo $field_info, AccountInterface $current_user) {
-    parent::__construct($entity_manager);
+    $this->entityManager = $entity_manager;
     $this->fieldInfo = $field_info;
     $this->currentUser = $current_user;
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function init(array &$form_state) {
-    $comment = $this->entity;
-
-    // Make the comment inherit the current content language unless specifically
-    // set.
-    if ($comment->isNew()) {
-      $language_content = \Drupal::languageManager()->getLanguage(Language::TYPE_CONTENT);
-      $comment->langcode->value = $language_content->id;
-    }
-
-    parent::init($form_state);
-  }
-
   /**
    * Overrides Drupal\Core\Entity\EntityFormController::form().
    */
@@ -215,6 +207,13 @@ public function form(array $form, array &$form_state) {
       '#value' => ($comment->id() ? !$comment->uid->target_id : $this->currentUser->isAnonymous()),
     );
 
+    // Make the comment inherit the current content language unless specifically
+    // set.
+    if ($comment->isNew()) {
+      $language_content = language(Language::TYPE_CONTENT);
+      $comment->langcode->value = $language_content->id;
+    }
+
     // Add internal comment properties.
     $original = $comment->getUntranslated();
     foreach (array('cid', 'pid', 'entity_id', 'entity_type', 'field_id', 'uid', 'langcode') as $key) {
diff --git a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
index d79363b611e881d2cea65ef62e509b10dfed198c..22dfb095971917f2cd3047ef8452a6363875704f 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentViewBuilder.php
@@ -23,6 +23,13 @@
  */
 class CommentViewBuilder extends EntityViewBuilder implements EntityViewBuilderInterface, EntityControllerInterface {
 
+  /**
+   * The entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
   /**
    * The field info service.
    *
@@ -50,7 +57,6 @@ class CommentViewBuilder extends EntityViewBuilder implements EntityViewBuilderI
   public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
     return new static(
       $entity_type,
-      $entity_info,
       $container->get('entity.manager'),
       $container->get('field.info'),
       $container->get('module_handler'),
@@ -63,8 +69,6 @@ public static function createInstance(ContainerInterface $container, $entity_typ
    *
    * @param string $entity_type
    *   The entity type.
-   * @param array $entity_info
-   *   The entity information array.
    * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
    *   The entity manager service.
    * @param \Drupal\field\FieldInfo $field_info
@@ -74,8 +78,9 @@ public static function createInstance(ContainerInterface $container, $entity_typ
    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
    *   The CSRF token manager service.
    */
-  public function __construct($entity_type, array $entity_info, EntityManagerInterface $entity_manager, FieldInfo $field_info, ModuleHandlerInterface $module_handler, CsrfTokenGenerator $csrf_token) {
-    parent::__construct($entity_type, $entity_info, $entity_manager);
+  public function __construct($entity_type, EntityManagerInterface $entity_manager, FieldInfo $field_info, ModuleHandlerInterface $module_handler, CsrfTokenGenerator $csrf_token) {
+    parent::__construct($entity_type);
+    $this->entityManager = $entity_manager;
     $this->fieldInfo = $field_info;
     $this->moduleHandler = $module_handler;
     $this->csrfToken = $csrf_token;
diff --git a/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php b/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php
index 60b20369c0cc8beee8899cba8284b86fb32bde76..07f3146e6156e1528271462796e48b2eae18da44 100644
--- a/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php
+++ b/core/modules/comment/lib/Drupal/comment/Form/DeleteForm.php
@@ -10,7 +10,6 @@
 use Drupal\comment\CommentManagerInterface;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Entity\ContentEntityConfirmFormBase;
-use Drupal\Core\Entity\EntityManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -28,13 +27,10 @@ class DeleteForm extends ContentEntityConfirmFormBase {
   /**
    * Constructs a DeleteForm object.
    *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
    * @param \Drupal\comment\CommentManagerInterface $comment_manager
    *   The comment manager service.
    */
-  public function __construct(EntityManagerInterface $entity_manager, CommentManagerInterface $comment_manager) {
-    parent::__construct($entity_manager);
+  public function __construct(CommentManagerInterface $comment_manager) {
     $this->commentManager = $comment_manager;
   }
 
@@ -43,7 +39,6 @@ public function __construct(EntityManagerInterface $entity_manager, CommentManag
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('entity.manager'),
       $container->get('comment.manager')
     );
   }
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index 2af6130334a08484c9af0c704df9677fc04f8dce..b31b8d8cb2bb917d6ef5a8d19aca56d2c7d63aac 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -323,12 +323,7 @@ function content_translation_translate_access(EntityInterface $entity) {
  */
 function content_translation_view_access(EntityInterface $entity, $langcode, AccountInterface $account = NULL) {
   $entity_type = $entity->entityType();
-  $info = $entity->entityInfo();
-  $permission = "translate $entity_type";
-  if (!empty($info['permission_granularity']) && $info['permission_granularity'] == 'bundle') {
-    $permission = "translate {$entity->bundle()} $entity_type";
-  }
-  return !empty($entity->translation[$langcode]['status']) || user_access('translate any entity', $account) || user_access($permission, $account);
+  return !empty($entity->translation[$langcode]['status']) || user_access('translate any entity', $account) || user_access("translate $entity_type entities", $account);
 }
 
 /**
@@ -632,10 +627,7 @@ function content_translation_permission() {
  * Implements hook_form_alter().
  */
 function content_translation_form_alter(array &$form, array &$form_state) {
-  $form_controller = content_translation_form_controller($form_state);
-  $entity = $form_controller ? $form_controller->getEntity() : NULL;
-
-  if ($entity instanceof ContentEntityInterface && $entity->isTranslatable() && count($entity->getTranslationLanguages()) > 1) {
+  if (($form_controller = content_translation_form_controller($form_state)) && ($entity = $form_controller->getEntity()) && !$entity->isNew() && $entity instanceof ContentEntityInterface && $entity->isTranslatable()) {
     $controller = content_translation_controller($entity->entityType());
     $controller->entityFormAlter($form, $form_state, $entity);
 
@@ -658,16 +650,28 @@ function content_translation_form_alter(array &$form, array &$form_state) {
 }
 
 /**
- * Implements hook_language_fallback_candidates_OPERATION_alter().
+ * Implements hook_field_language_alter().
  *
  * Performs language fallback for unaccessible translations.
  */
-function content_translation_language_fallback_candidates_entity_view_alter(&$candidates, $context) {
-  $entity = $context['data'];
-  foreach ($entity->getTranslationLanguages() as $langcode => $language) {
-    if (!content_translation_view_access($entity, $langcode)) {
-      unset($candidates[$langcode]);
+function content_translation_field_language_alter(&$display_language, $context) {
+  $entity = $context['entity'];
+  $entity_type = $entity->entityType();
+
+  if ($entity instanceof ContentEntityInterface && isset($entity->translation[$context['langcode']]) && $entity->isTranslatable() && !content_translation_view_access($entity, $context['langcode'])) {
+    $instances = field_info_instances($entity_type, $entity->bundle());
+    // Avoid altering the real entity.
+    $entity = clone($entity);
+    $entity_langcode = $entity->getUntranslated()->language()->id;
+
+    foreach ($entity->translation as $langcode => $translation) {
+      if ($langcode == $context['langcode'] || !content_translation_view_access($entity, $langcode)) {
+        $entity->removeTranslation($langcode);
+      }
     }
+
+    // Find the new fallback values.
+    field_language_fallback($display_language, $entity, $context['langcode']);
   }
 }
 
diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php
index c24e064b6c031e461b6334028582c8b3e245bb30..21c84657b8c78ee1efed492aa5f4660514d4043d 100644
--- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php
+++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php
@@ -34,18 +34,18 @@ abstract class ContentTranslationUITest extends ContentTranslationTestBase {
    * Tests the basic translation UI.
    */
   function testTranslationUI() {
-    $this->doTestBasicTranslation();
+    $this->assertBasicTranslation();
     $this->doTestTranslationOverview();
-    $this->doTestOutdatedStatus();
-    $this->doTestPublishedStatus();
-    $this->doTestAuthoringInfo();
-    $this->doTestTranslationDeletion();
+    $this->assertOutdatedStatus();
+    $this->assertPublishedStatus();
+    $this->assertAuthoringInfo();
+    $this->assertTranslationDeletion();
   }
 
   /**
    * Tests the basic translation workflow.
    */
-  protected function doTestBasicTranslation() {
+  protected function assertBasicTranslation() {
     // Create a new test entity with original values in the default language.
     $default_langcode = $this->langcodes[0];
     $values[$default_langcode] = $this->getNewEntityValues($default_langcode);
@@ -117,7 +117,7 @@ protected function doTestTranslationOverview() {
   /**
    * Tests up-to-date status tracking.
    */
-  protected function doTestOutdatedStatus() {
+  protected function assertOutdatedStatus() {
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
     $langcode = 'fr';
     $default_langcode = $this->langcodes[0];
@@ -150,7 +150,7 @@ protected function doTestOutdatedStatus() {
   /**
    * Tests the translation publishing status.
    */
-  protected function doTestPublishedStatus() {
+  protected function assertPublishedStatus() {
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
     $path = $this->controller->getEditPath($entity);
 
@@ -172,7 +172,7 @@ protected function doTestPublishedStatus() {
   /**
    * Tests the translation authoring information.
    */
-  protected function doTestAuthoringInfo() {
+  protected function assertAuthoringInfo() {
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
     $path = $this->controller->getEditPath($entity);
     $values = array();
@@ -194,8 +194,8 @@ protected function doTestAuthoringInfo() {
 
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
     foreach ($this->langcodes as $langcode) {
-      $this->assertEqual($entity->translation[$langcode]['uid'], $values[$langcode]['uid'], 'Translation author correctly stored.');
-      $this->assertEqual($entity->translation[$langcode]['created'], $values[$langcode]['created'], 'Translation date correctly stored.');
+      $this->assertEqual($entity->translation[$langcode]['uid'] == $values[$langcode]['uid'], 'Translation author correctly stored.');
+      $this->assertEqual($entity->translation[$langcode]['created'] == $values[$langcode]['created'], 'Translation date correctly stored.');
     }
 
     // Try to post non valid values and check that they are rejected.
@@ -207,14 +207,14 @@ protected function doTestAuthoringInfo() {
     );
     $this->drupalPostForm($path, $edit, $this->getFormSubmitAction($entity));
     $this->assertTrue($this->xpath('//div[contains(@class, "error")]//ul'), 'Invalid values generate a list of form errors.');
-    $this->assertEqual($entity->translation[$langcode]['uid'], $values[$langcode]['uid'], 'Translation author correctly kept.');
-    $this->assertEqual($entity->translation[$langcode]['created'], $values[$langcode]['created'], 'Translation date correctly kept.');
+    $this->assertEqual($entity->translation[$langcode]['uid'] == $values[$langcode]['uid'], 'Translation author correctly kept.');
+    $this->assertEqual($entity->translation[$langcode]['created'] == $values[$langcode]['created'], 'Translation date correctly kept.');
   }
 
   /**
    * Tests translation deletion.
    */
-  protected function doTestTranslationDeletion() {
+  protected function assertTranslationDeletion() {
     // Confirm and delete a translation.
     $langcode = 'fr';
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php
index 29a46b5aff6eebce084664082e73a4b1f10aceee..803fbe3cc34100c8342b3bf38648b3a7899c2b88 100644
--- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php
+++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayModeTest.php
@@ -40,11 +40,11 @@ public function testEntityViewModeUI() {
     $this->drupalGet('admin/structure/display-modes/view');
     $this->assertResponse(200);
 
-    $this->drupalGet('admin/structure/display-modes/view/add/entity_test_mulrev');
+    $this->drupalGet('admin/structure/display-modes/view/add/entity_test_mul');
     $this->assertResponse(404);
 
     $this->drupalGet('admin/structure/display-modes/view/add');
-    $this->assertNoLink(t('Test entity - revisions and data table'), 'An entity type with no view builder cannot have view modes.');
+    $this->assertNoLink(t('Test entity - data table'), 'An entity type with no view builder cannot have view modes.');
 
     // Test adding a view mode.
     $this->clickLink(t('Test entity'));
diff --git a/core/modules/field/config/field.settings.yml b/core/modules/field/config/field.settings.yml
index b6172c13a6984adb16b128babeb639584ced0514..0a9ebdffe1ce103df2ce3c721c2f37cedbc0ae1d 100644
--- a/core/modules/field/config/field.settings.yml
+++ b/core/modules/field/config/field.settings.yml
@@ -1 +1,2 @@
+language_fallback: true
 purge_batch_size: 10
diff --git a/core/modules/field/config/schema/field.schema.yml b/core/modules/field/config/schema/field.schema.yml
index 424132b51c8489041883eca9c400c4b06ded0337..9996784750f450f379571bd5256a1baa33466b10 100644
--- a/core/modules/field/config/schema/field.schema.yml
+++ b/core/modules/field/config/schema/field.schema.yml
@@ -4,6 +4,9 @@ field.settings:
   type: mapping
   label: 'Field settings'
   mapping:
+    language_fallback:
+      type: boolean
+      label: 'Whether the field display falls back to global language fallback configuration'
     purge_batch_size:
       type: integer
       label: 'Maximum number of field data records to purge'
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index c252e2ed05a7435b2fa811daabb8e490fe2f87ce..b4f0198272f20d1e7fd2277b78bb57ccd4b1727c 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -414,6 +414,27 @@ function hook_field_attach_view_alter(&$output, $context) {
   }
 }
 
+/**
+ * Perform alterations on field_language() values.
+ *
+ * This hook is invoked to alter the array of display language codes for the
+ * given entity.
+ *
+ * @param $display_langcode
+ *   A reference to an array of language codes keyed by field name.
+ * @param $context
+ *   An associative array containing:
+ *   - entity: The entity with fields to render.
+ *   - langcode: The language code $entity has to be displayed in.
+ */
+function hook_field_language_alter(&$display_langcode, $context) {
+  // Do not apply core language fallback rules if they are disabled or if Locale
+  // is not registered as a translation handler.
+  if (field_language_fallback_enabled() && field_has_translation_handler($context['entity']->entityType())) {
+    field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
+  }
+}
+
 /**
  * Alter field_available_languages() values.
  *
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index 5567afd711eb210a184c6e66de5c73f169b66ddf..548cc7415a287361fba82143e8a296a78aeb6046 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -120,21 +120,19 @@ function field_invoke_method($method, $target_function, EntityInterface $entity,
       $langcodes = _field_language_suggestion($available_langcodes, $options['langcode'], $field_name);
 
       foreach ($langcodes as $langcode) {
-        if ($entity->hasTranslation($langcode)) {
-          $items = $entity->getTranslation($langcode)->get($field_name);
-          $items->filterEmptyValues();
+        $items = $entity->getTranslation($langcode)->get($field_name);
+        $items->filterEmptyValues();
 
-          $result = $target->$method($items, $a, $b);
+        $result = $target->$method($items, $a, $b);
 
-          if (isset($result)) {
-            // For methods with array results, we merge results together.
-            // For methods with scalar results, we collect results in an array.
-            if (is_array($result)) {
-              $return = array_merge($return, $result);
-            }
-            else {
-              $return[] = $result;
-            }
+        if (isset($result)) {
+          // For methods with array results, we merge results together.
+          // For methods with scalar results, we collect results in an array.
+          if (is_array($result)) {
+            $return = array_merge($return, $result);
+          }
+          else {
+            $return[] = $result;
           }
         }
       }
@@ -225,12 +223,10 @@ function field_invoke_method_multiple($method, $target_function, array $entities
         $langcode = !empty($options['langcode'][$id]) ? $options['langcode'][$id] : $options['langcode'];
         $langcodes = _field_language_suggestion($available_langcodes, $langcode, $field_name);
         foreach ($langcodes as $langcode) {
-          if ($entity->hasTranslation($langcode)) {
-            // Group the items corresponding to the current field.
-            $items = $entity->getTranslation($langcode)->get($field_name);
-            $items->filterEmptyValues();
-            $grouped_items[$instance_uuid][$langcode][$id] = $items;
-          }
+          // Group the items corresponding to the current field.
+          $items = $entity->getTranslation($langcode)->get($field_name);
+          $items->filterEmptyValues();
+          $grouped_items[$instance_uuid][$langcode][$id] = $items;
         }
       }
     }
diff --git a/core/modules/field/field.deprecated.inc b/core/modules/field/field.deprecated.inc
index 8ac2bc2c7b76b46c73f40585421e3624d00ca176..b85380eddc2c25905a466fc9bc4a26ec7eeccb68 100644
--- a/core/modules/field/field.deprecated.inc
+++ b/core/modules/field/field.deprecated.inc
@@ -7,7 +7,6 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
-use Drupal\Core\Language\Language;
 use Drupal\entity\Entity\EntityDisplay;
 use Drupal\field\Field;
 
@@ -859,80 +858,3 @@ function field_access($op, FieldInterface $field, $entity_type, $entity = NULL,
   $items = $entity ? $entity->get($field->id()) : NULL;
   return $access_controller->fieldAccess($op, $field, $account, $items);
 }
-
-/**
- * Ensures that a given language code is valid.
- *
- * Checks whether the given language code is one of the enabled language codes.
- * Otherwise, it returns the current, global language code; or the site's
- * default language code, if the additional parameter $default is TRUE.
- *
- * @param $langcode
- *   The language code to validate.
- * @param $default
- *   Whether to return the default language code or the current language code in
- *   case $langcode is invalid.
- *
- * @return
- *   A valid language code.
- *
- * @deprecated This has been deprecated in favor of the Entity Field API.
- */
-function field_valid_language($langcode, $default = TRUE) {
-  $languages = field_content_languages();
-  if (in_array($langcode, $languages)) {
-    return $langcode;
-  }
-  return $default ? language_default()->id : language(Language::TYPE_CONTENT)->id;
-}
-
-/**
- * Returns the display language code for the fields attached to the given
- * entity.
- *
- * The actual language code for each given field is determined based on the
- * requested language code and the actual data available in the fields
- * themselves.
- * If there is no registered translation handler for the given entity type, the
- * display language code to be used is just Language::LANGCODE_NOT_SPECIFIED, as
- * no other language code is allowed by field_available_languages().
- *
- * If translation handlers are found, we let modules provide alternative display
- * language codes for fields not having the requested language code available.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- *   The entity to be displayed.
- * @param $field_name
- *   (optional) The name of the field to be displayed. Defaults to NULL. If
- *   no value is specified, the display language codes for every field attached
- *   to the given entity will be returned.
- * @param $langcode
- *   (optional) The language code $entity has to be displayed in. Defaults to
- *   NULL. If no value is given the current language will be used.
- *
- * @return
- *   A language code if a field name is specified, an array of language codes
- *   keyed by field name otherwise.
- *
- * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates()
- * @see \Drupal\Core\Entity\EntityInterface::getFieldLangcode()
- *
- * @deprecated This has been deprecated in favor of the Entity Field API.
- */
-function field_language(EntityInterface $entity, $field_name = NULL, $langcode = NULL) {
-  $langcode = \Drupal::entityManager()->getTranslationFromContext($entity, $langcode)->language()->id;
-  $definitions = $entity->getPropertyDefinitions();
-  $translatable = field_has_translation_handler($entity->entityType());
-  if (!isset($field_name)) {
-    $display_langcodes = array();
-    foreach ($definitions as $name => $definition) {
-      if (!empty($definition['configurable'])) {
-        $display_langcodes[$name] = $translatable ? $langcode : Language::LANGCODE_NOT_SPECIFIED;
-      }
-    }
-    return $display_langcodes;
-  }
-  elseif (!empty($definitions[$field_name]['configurable'])) {
-    return $translatable ? $langcode : Language::LANGCODE_NOT_SPECIFIED;
-  }
-}
diff --git a/core/modules/field/field.install b/core/modules/field/field.install
index 55d6ff492d0f23f563a153340f8973ce7d13ff1e..2da4aec72bf95d6ead0c4b185c9c1cd2a08d27ad 100644
--- a/core/modules/field/field.install
+++ b/core/modules/field/field.install
@@ -442,7 +442,10 @@ function field_update_8003() {
  * @ingroup config_upgrade
  */
 function field_update_8004() {
-  // Do nothing: the former update code has been moved to locale_update_8018().
+  update_variable_set('field_language_fallback', TRUE);
+  update_variables_to_config('field.settings', array(
+    'field_language_fallback' => 'language_fallback',
+  ));
 }
 
 /**
diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc
index 68493c7113d511899bde4b573a5cede11819d683..96ecabbf90a370da46c22d2dd9fbab1b5de23e17 100644
--- a/core/modules/field/field.multilingual.inc
+++ b/core/modules/field/field.multilingual.inc
@@ -65,6 +65,49 @@
  */
 
 
+/**
+ * Applies language fallback rules to the fields attached to the given entity.
+ *
+ * Core language fallback rules simply check if fields have a field translation
+ * for the requested language code. If so, the requested language is returned,
+ * otherwise all the fallback candidates are inspected to see if there is a
+ * field translation available in another language.
+ * By default this is called by field_field_language_alter(), but this
+ * behavior can be disabled by setting the 'field.settings.language_fallback'
+ * variable to FALSE.
+ *
+ * @param $field_langcodes
+ *   A reference to an array of language codes keyed by field name.
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity to be displayed.
+ * @param $langcode
+ *   The language code $entity has to be displayed in.
+ */
+function field_language_fallback(&$field_langcodes, EntityInterface $entity, $langcode) {
+  // Lazily init fallback candidates to avoid unnecessary calls.
+  $fallback_candidates = NULL;
+
+  foreach ($field_langcodes as $field_name => $field_langcode) {
+    // If the requested language is defined for the current field use it,
+    // otherwise search for a fallback value among the fallback candidates.
+    if (_field_translated_value_exists($entity, $langcode, $field_name)) {
+      $field_langcodes[$field_name] = $langcode;
+    }
+    else {
+      if (!isset($fallback_candidates)) {
+        require_once DRUPAL_ROOT . '/core/includes/language.inc';
+        $fallback_candidates = language_fallback_get_candidates();
+      }
+      foreach ($fallback_candidates as $fallback_langcode) {
+        if (_field_translated_value_exists($entity, $fallback_langcode, $field_name)) {
+          $field_langcodes[$field_name] = $fallback_langcode;
+          break;
+        }
+      }
+    }
+  }
+}
+
 /**
  * Collects the available language codes for the given entity type and field.
  *
@@ -152,6 +195,13 @@ function field_content_languages() {
   return array_keys(language_list(Language::STATE_ALL));
 }
 
+/**
+ * Checks whether field language fallback is enabled.
+ */
+function field_language_fallback_enabled() {
+  return language_multilingual() && \Drupal::config('field.settings')->get('language_fallback');
+}
+
 /**
  * Checks whether a field has language support.
  *
@@ -192,3 +242,126 @@ function field_has_translation_handler($entity_type, $handler = NULL) {
   $info = entity_get_info($entity_type);
   return !empty($info['translatable']);
 }
+
+/**
+ * Ensures that a given language code is valid.
+ *
+ * Checks whether the given language code is one of the enabled language codes.
+ * Otherwise, it returns the current, global language code; or the site's
+ * default language code, if the additional parameter $default is TRUE.
+ *
+ * @param $langcode
+ *   The language code to validate.
+ * @param $default
+ *   Whether to return the default language code or the current language code in
+ *   case $langcode is invalid.
+ *
+ * @return
+ *   A valid language code.
+ */
+function field_valid_language($langcode, $default = TRUE) {
+  $languages = field_content_languages();
+  if (in_array($langcode, $languages)) {
+    return $langcode;
+  }
+  return $default ? language_default()->id : language(Language::TYPE_CONTENT)->id;
+}
+
+/**
+ * Returns the display language code for the fields attached to the given
+ * entity.
+ *
+ * The actual language code for each given field is determined based on the
+ * requested language code and the actual data available in the fields
+ * themselves.
+ * If there is no registered translation handler for the given entity type, the
+ * display language code to be used is just Language::LANGCODE_NOT_SPECIFIED, as no other
+ * language code is allowed by field_available_languages().
+ *
+ * If translation handlers are found, we let modules provide alternative display
+ * language codes for fields not having the requested language code available.
+ * Core language fallback rules are provided by field_language_fallback()
+ * which is called by field_field_language_alter().
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity to be displayed.
+ * @param $field_name
+ *   (optional) The name of the field to be displayed. Defaults to NULL. If
+ *   no value is specified, the display language codes for every field attached
+ *   to the given entity will be returned.
+ * @param $langcode
+ *   (optional) The language code $entity has to be displayed in. Defaults to
+ *   NULL. If no value is given the current language will be used.
+ *
+ * @return
+ *   A language code if a field name is specified, an array of language codes
+ *   keyed by field name otherwise.
+ */
+function field_language(EntityInterface $entity, $displayed_field_name = NULL, $langcode = NULL) {
+  $display_langcodes = &drupal_static(__FUNCTION__, array());
+  $id = $entity->id();
+  $bundle = $entity->bundle();
+  $entity_type = $entity->entityType();
+  $langcode = field_valid_language($langcode, FALSE);
+  if (!isset($display_langcodes[$entity_type][$id][$langcode])) {
+    $display_langcode = array();
+
+    // By default, display language is set to one of the locked languages
+    // if the field translation is not available. It is up to translation
+    // handlers to implement language fallback rules.
+    foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) {
+      if (_field_translated_value_exists($entity, $langcode, $field_name)) {
+        $display_langcode[$field_name] = $langcode;
+      }
+      else {
+        // If the field has a value for one of the locked languages, then use
+        // that language for display. If not, the default one will be
+        // Language::LANGCODE_NOT_SPECIFIED.
+        $display_langcode[$field_name] = Language::LANGCODE_NOT_SPECIFIED;
+        foreach (language_list(Language::STATE_LOCKED) as $language_locked) {
+          if (isset($entity->{$field_name}[$language_locked->id])) {
+            $display_langcode[$field_name] = $language_locked->id;
+            break;
+          }
+        }
+      }
+    }
+
+    if (field_has_translation_handler($entity_type)) {
+      $context = array(
+        'entity' => $entity,
+        'langcode' => $langcode,
+      );
+      // Do not apply core language fallback rules if they are disabled or if
+      // the entity does not have a translation handler registered.
+      if (field_language_fallback_enabled() && field_has_translation_handler($entity_type)) {
+        field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
+      }
+      drupal_alter('field_language', $display_langcode, $context);
+    }
+
+    $display_langcodes[$entity_type][$id][$langcode] = $display_langcode;
+  }
+
+  $display_langcode = $display_langcodes[$entity_type][$id][$langcode];
+
+  // Single-field mode.
+  if (isset($displayed_field_name)) {
+    return isset($display_langcode[$displayed_field_name]) ? $display_langcode[$displayed_field_name] : FALSE;
+  }
+
+  return $display_langcode;
+}
+
+/**
+ * Returns TRUE if a non-empty value exists for a given entity/language/field.
+ */
+function _field_translated_value_exists(EntityInterface $entity, $langcode, $field_name) {
+  if (!$entity->hasTranslation($langcode)) {
+    return FALSE;
+  }
+  $field = $entity->getTranslation($langcode)->$field_name;
+  $field->filterEmptyValues();
+  $value = $field->getValue();
+  return !empty($value);
+}
diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
index f5228d0c66360f41b7065419e729dd986bf5afeb..d89340f61763b9b91087a5d89eca380761fa2a5e 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
@@ -263,7 +263,14 @@ public function query($use_groupby = FALSE) {
           $this->view->display_handler->options['field_langcode']
         );
         $placeholder = $this->placeholder();
-        $langcode_fallback_candidates = $this->languageManager->getFallbackCandidates($langcode, array('operation' => 'views_query', 'data' => $this));
+        $langcode_fallback_candidates = array($langcode);
+        if (field_language_fallback_enabled()) {
+          require_once DRUPAL_ROOT . '/includes/language.inc';
+          $langcode_fallback_candidates = array_merge($langcode_fallback_candidates, language_fallback_get_candidates());
+        }
+        else {
+          $langcode_fallback_candidates[] = Language::LANGCODE_NOT_SPECIFIED;
+        }
         $this->query->addWhereExpression(0, "$column IN($placeholder) OR $column IS NULL", array($placeholder => $langcode_fallback_candidates));
       }
     }
@@ -863,12 +870,11 @@ function field_langcode(EntityInterface $entity) {
         $this->view->display_handler->options['field_language']
       );
 
-      // Give the Entity Field API a chance to fallback to a different language
-      // (or Language::LANGCODE_NOT_SPECIFIED), in case the field has no data
-      // for the selected language. field_view_field() does this as well, but
-      // since the returned language code is used before calling it, the
-      // fallback needs to happen explicitly.
-      $langcode = $this->entityManager->getTranslationFromContext($entity, $langcode)->language()->id;
+      // Give the Field Language API a chance to fallback to a different language
+      // (or Language::LANGCODE_NOT_SPECIFIED), in case the field has no data for the selected language.
+      // field_view_field() does this as well, but since the returned language code
+      // is used before calling it, the fallback needs to happen explicitly.
+      $langcode = field_language($entity, $this->field_info['field_name'], $langcode);
 
       return $langcode;
     }
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
index de2dd94ebcbeec3b99f7701fca41b01a5eb2ccbc..b381cf57c872bdfa8779bd4df59f89ccfd110208 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php
@@ -80,8 +80,6 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $this->installConfig(array('language'));
-
     $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
 
     $this->entity_type = 'entity_test';
@@ -161,7 +159,6 @@ function testTranslatableFieldSaveLoad() {
     $field_translations = array();
     $available_langcodes = field_available_languages($entity_type, $this->field);
     $this->assertTrue(count($available_langcodes) > 1, 'Field is translatable.');
-    $available_langcodes = array_keys(language_list());
     $entity->langcode->value = reset($available_langcodes);
     foreach ($available_langcodes as $langcode) {
       $field_translations[$langcode] = $this->_generateTestFieldValues($this->field->getFieldCardinality());
@@ -231,4 +228,100 @@ function testTranslatableFieldSaveLoad() {
     }
   }
 
+  /**
+   * Tests display language logic for translatable fields.
+   */
+  function testFieldDisplayLanguage() {
+    $field_name = drupal_strtolower($this->randomName() . '_field_name');
+    $entity_type = 'entity_test';
+    $bundle = 'entity_test';
+
+    // We need an additional field here to properly test display language
+    // suggestions.
+    $field = array(
+      'name' => $field_name,
+      'entity_type' => $entity_type,
+      'type' => 'test_field',
+      'cardinality' => 2,
+      'translatable' => TRUE,
+    );
+    entity_create('field_entity', $field)->save();
+
+    $instance = array(
+      'field_name' => $field['name'],
+      'entity_type' => $entity_type,
+      'bundle' => $bundle,
+    );
+    entity_create('field_instance', $instance)->save();
+
+    $enabled_langcodes = field_content_languages();
+    $entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));;
+    $entity->langcode->value = reset($enabled_langcodes);
+    $instances = field_info_instances($entity_type, $bundle);
+
+    $langcodes = array();
+    // This array is used to store, for each field name, which one of the locked
+    // languages will be used for display.
+    $locked_languages = array();
+
+    // Generate field translations for languages different from the first
+    // enabled.
+    foreach ($instances as $instance) {
+      $field_name = $instance->getFieldName();
+      $field = $instance->getField();
+      do {
+        // Index 0 is reserved for the requested language, this way we ensure
+        // that no field is actually populated with it.
+        $langcode = $enabled_langcodes[mt_rand(1, count($enabled_langcodes) - 1)];
+      }
+      while (isset($langcodes[$langcode]));
+      $langcodes[$langcode] = TRUE;
+      $entity->getTranslation($langcode)->{$field_name}->setValue($this->_generateTestFieldValues($field->getFieldCardinality()));
+      // If the langcode is one of the locked languages, then that one
+      // will also be used for display. Otherwise, the default one should be
+      // used, which is Language::LANGCODE_NOT_SPECIFIED.
+      if (language_is_locked($langcode)) {
+        $locked_languages[$field_name] = $langcode;
+      }
+      else {
+        $locked_languages[$field_name] = Language::LANGCODE_NOT_SPECIFIED;
+      }
+    }
+
+    // Test multiple-fields display languages for untranslatable entities.
+    field_test_entity_info_translatable($entity_type, FALSE);
+    drupal_static_reset('field_language');
+    $requested_langcode = $enabled_langcodes[0];
+    $display_langcodes = field_language($entity, NULL, $requested_langcode);
+    foreach ($instances as $instance) {
+      $field_name = $instance->getFieldName();
+      $this->assertTrue($display_langcodes[$field_name] == $locked_languages[$field_name], format_string('The display language for field %field_name is %language.', array('%field_name' => $field_name, '%language' => $locked_languages[$field_name])));
+    }
+
+    // Test multiple-fields display languages for translatable entities.
+    field_test_entity_info_translatable($entity_type, TRUE);
+    drupal_static_reset('field_language');
+    $display_langcodes = field_language($entity, NULL, $requested_langcode);
+    foreach ($instances as $instance) {
+      $field_name = $instance->getFieldName();
+      $langcode = $display_langcodes[$field_name];
+      // As the requested language was not assinged to any field, if the
+      // returned language is defined for the current field, core fallback rules
+      // were successfully applied.
+      $this->assertTrue(!empty($entity->getTranslation($langcode)->{$field_name}) && $langcode != $requested_langcode, format_string('The display language for the field %field_name is %language.', array('%field_name' => $field_name, '%language' => $langcode)));
+    }
+
+    // Test single-field display language.
+    drupal_static_reset('field_language');
+    $langcode = field_language($entity, $this->field_name, $requested_langcode);
+    $this->assertTrue(!empty($entity->getTranslation($langcode)->{$this->field_name}) && $langcode != $requested_langcode, format_string('The display language for the (single) field %field_name is %language.', array('%field_name' => $field_name, '%language' => $langcode)));
+
+    // Test field_language() basic behavior without language fallback.
+    \Drupal::state()->set('field_test.language_fallback', FALSE);
+    $entity->getTranslation($requested_langcode)->{$this->field_name}->value = mt_rand(1, 127);
+    drupal_static_reset('field_language');
+    $display_langcode = field_language($entity, $this->field_name, $requested_langcode);
+    $this->assertEqual($display_langcode, $requested_langcode, 'Display language behave correctly when language fallback is disabled');
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
index 90d3ef7c592aecac5608da5fcabfc1885c7d89dd..8ddb73a14b17073766b0c5c9df976a77e38f6df6 100644
--- a/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/TranslationWebTest.php
@@ -109,7 +109,6 @@ function testFieldFormTranslationRevisions() {
     $field_name = $this->field->getFieldName();
 
     // Store the field translations.
-    ksort($available_langcodes);
     $entity->langcode->value = key($available_langcodes);
     foreach ($available_langcodes as $langcode => $value) {
       $entity->getTranslation($langcode)->{$field_name}->value = $value + 1;
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index c02a40c6b7476f703519f705601891f8a0bf8d9a..992e6ef95e2d4d8893b4d0787ce547dd9e09bdb6 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -62,6 +62,15 @@ function field_test_field_available_languages_alter(&$langcodes, $context) {
   }
 }
 
+/**
+ * Implements hook_field_language_alter().
+ */
+function field_test_field_language_alter(&$display_langcode, $context) {
+  if (\Drupal::state()->get('field_test.language_fallback') ?: TRUE) {
+    field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
+  }
+}
+
 /**
  * Store and retrieve keyed data for later verification by unit tests.
  *
diff --git a/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php b/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php
index 7b758ef48f7c3aa093fea4f461db9cfc9b56a71d..56bbb5169b7df6e6245471c86571975366e69bd1 100644
--- a/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php
+++ b/core/modules/forum/lib/Drupal/forum/Form/ForumFormController.php
@@ -8,7 +8,11 @@
 namespace Drupal\forum\Form;
 
 use Drupal\Core\Cache\Cache;
+use Drupal\Core\Config\ConfigFactory;
 use Drupal\taxonomy\TermFormController;
+use Drupal\taxonomy\TermStorageControllerInterface;
+use Drupal\taxonomy\VocabularyStorageControllerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Base form controller for forum term edit forms.
@@ -29,6 +33,47 @@ class ForumFormController extends TermFormController {
    */
   protected $urlStub = 'forum';
 
+  /**
+   * The forum config.
+   *
+   * @var \Drupal\Core\Config\Config
+   */
+  protected $config;
+
+  /**
+   * Term Storage Controller.
+   *
+   * @var \Drupal\taxonomy\TermStorageControllerInterface
+   */
+  protected $termStorage;
+
+  /**
+   * Constructs a new ForumFormController object.
+   *
+   * @param \Drupal\taxonomy\VocabularyStorageControllerInterface $vocab_storage
+   *   The vocabulary storage.
+   * @param \Drupal\Core\Config\ConfigFactory $config_factory
+   *   The config factory service.
+   * @param \Drupal\taxonomy\TermStorageControllerInterface $term_storage
+   *   The term storage.
+   */
+  public function __construct(VocabularyStorageControllerInterface $vocab_storage, ConfigFactory $config_factory, TermStorageControllerInterface $term_storage) {
+    parent::__construct($vocab_storage, $config_factory);
+    $this->termStorage = $term_storage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    $entity_manager = $container->get('entity.manager');
+    return new static(
+      $entity_manager->getStorageController('taxonomy_vocabulary'),
+      $container->get('config.factory'),
+      $entity_manager->getStorageController('taxonomy_term')
+    );
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -76,9 +121,8 @@ public function buildEntity(array $form, array &$form_state) {
    */
   public function save(array $form, array &$form_state) {
     $term = $this->entity;
-    $term_storage = $this->entityManager->getStorageController('taxonomy_term');
-    $status = $term_storage->save($term);
 
+    $status = $this->termStorage->save($term);
     switch ($status) {
       case SAVED_NEW:
         drupal_set_message($this->t('Created new @type %term.', array('%term' => $term->label(), '@type' => $this->forumFormType)));
diff --git a/core/modules/language/language.api.php b/core/modules/language/language.api.php
index d0a31c4992a903bcafc4cb7199956365f58ee328..cba3f966261c3f6201973894e1877fac9ce5c165 100644
--- a/core/modules/language/language.api.php
+++ b/core/modules/language/language.api.php
@@ -57,40 +57,6 @@ function hook_language_delete($language) {
     ->execute();
 }
 
-/**
- * Allow modules to alter the language fallback candidates.
- *
- * @param array $candidates
- *   An array of language codes whose order will determine the language fallback
- *   order.
- * @param array $context
- *   A language fallback context.
- *
- * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates()
- */
-function hook_language_fallback_candidates_alter(array &$candidates, array $context) {
-  $candidates = array_reverse($candidates);
-}
-
-/**
- * Allow modules to alter the fallback candidates for specific operations.
- *
- * @param array $candidates
- *   An array of language codes whose order will determine the language fallback
- *   order.
- * @param array $context
- *   A language fallback context.
- *
- * @see \Drupal\Core\Language\LanguageManager::getFallbackCandidates()
- */
-function hook_language_fallback_candidates_OPERATION_alter(array &$candidates, array $context) {
-  // We know that the current OPERATION deals with entities so no need to check
-  // here.
-  if ($context['data']->entityType() == 'node') {
-    $candidates = array_reverse($candidates);
-  }
-}
-
 /**
  * @} End of "addtogroup hooks".
  */
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageFallbackTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageFallbackTest.php
deleted file mode 100644
index ba50def0cce576b707afb3cdc55cb921af91a1df..0000000000000000000000000000000000000000
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageFallbackTest.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\language\Tests\LanguageFallbackTest.
- */
-
-namespace Drupal\language\Tests;
-
-use Drupal\Core\Language\Language;
-use Drupal\simpletest\DrupalUnitTestBase;
-
-/**
- * Tests the language fallback behavior.
- */
-class LanguageFallbackTest extends DrupalUnitTestBase {
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Language fallback',
-      'description' => 'Tests the language fallback behavior.',
-      'group' => 'Language',
-    );
-  }
-
-  /**
-   * The state storage service.
-   *
-   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
-   */
-  protected $state;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->enableModules(array('language', 'language_test'));
-    $this->installConfig(array('language'));
-
-    $this->state = $this->container->get('state');
-
-    for ($i = 0; $i < 3; $i++) {
-      $language = new Language();
-      $language->id = $this->randomName(2);
-      $language->weight = -$i;
-      language_save($language);
-    }
-  }
-
-  /**
-   * Tests language fallback candidates.
-   */
-  public function testCandidates() {
-    $manager = $this->getLanguageManager();
-    $expected = array_keys(language_list() + array(Language::LANGCODE_NOT_SPECIFIED => NULL));
-
-    // Check that language fallback candidates by default are all the available
-    // languages sorted by weight.
-    $candidates = $manager->getFallbackCandidates();
-    $this->assertEqual(array_values($candidates), $expected, 'Language fallback candidates are properly returned.');
-
-    // Check that candidates are alterable.
-    $this->state->set('language_test.fallback_alter.candidates', TRUE);
-    $expected = array_slice($expected, 0, count($expected) - 1);
-    $candidates = $manager->getFallbackCandidates();
-    $this->assertEqual(array_values($candidates), $expected, 'Language fallback candidates are alterable.');
-
-    // Check that candidates are alterable for specific operations.
-    $this->state->set('language_test.fallback_alter.candidates', FALSE);
-    $this->state->set('language_test.fallback_operation_alter.candidates', TRUE);
-    $expected[] = Language::LANGCODE_NOT_SPECIFIED;
-    $expected[] = Language::LANGCODE_NOT_APPLICABLE;
-    $candidates = $manager->getFallbackCandidates(NULL, array('operation' => 'test'));
-    $this->assertEqual(array_values($candidates), $expected, 'Language fallback candidates are alterable for specific operations.');
-
-    // Check that when the site is monolingual no language fallback is applied.
-    $default_langcode = language_default()->id;
-    foreach (language_list() as $langcode => $language) {
-      if ($langcode != $default_langcode) {
-        language_delete($langcode);
-      }
-    }
-    $candidates = $this->getLanguageManager()->getFallbackCandidates();
-    $this->assertEqual(array_values($candidates), array(Language::LANGCODE_DEFAULT), 'Language fallback is not applied when the Language module is not enabled.');
-  }
-
-  /**
-   * Returns the language manager service.
-   *
-   * @return \Drupal\Core\Language\LanguageManager
-   *   The language manager.
-   */
-  protected function getLanguageManager() {
-    return $this->container->get('language_manager');
-  }
-
-}
diff --git a/core/modules/language/tests/language_test/language_test.module b/core/modules/language/tests/language_test/language_test.module
index 8e8cbaf97c2c13721eb87837eb605342a05aa90d..33c2b36b5766e59a29f1099c1f1f74581412daf8 100644
--- a/core/modules/language/tests/language_test/language_test.module
+++ b/core/modules/language/tests/language_test/language_test.module
@@ -109,22 +109,3 @@ function language_test_store_language_negotiation() {
 function language_test_language_negotiation_method($languages) {
   return 'it';
 }
-
-/**
- * Implements hook_language_fallback_candidates_alter().
- */
-function language_test_language_fallback_candidates_alter(array &$candidates, array $context) {
-  if (Drupal::state()->get('language_test.fallback_alter.candidates')) {
-    unset($candidates[Language::LANGCODE_NOT_SPECIFIED]);
-  }
-}
-
-/**
- * Implements hook_language_fallback_candidates_OPERATION_alter().
- */
-function language_test_language_fallback_candidates_test_alter(array &$candidates, array $context) {
-  if (Drupal::state()->get('language_test.fallback_operation_alter.candidates')) {
-    $langcode = Language::LANGCODE_NOT_APPLICABLE;
-    $candidates[$langcode] = $langcode;
-  }
-}
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index c55e203c2173e89b86828a2fc23dfc4b053d1a80..3ab0247b2f6b88750a7b2254b0ceea651cead38f 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -964,15 +964,6 @@ function locale_update_8017() {
   ));
 }
 
-/**
- * Removes the field language fallback settings as it is no longer supported.
- *
- * @ingroup config_upgrade
- */
-function locale_update_8018() {
-  update_variable_del('locale_field_language_fallback');
-}
-
 /**
  * @} End of "addtogroup updates-7.x-to-8.x".
  * The next series of updates should start at 9000.
diff --git a/core/modules/node/lib/Drupal/node/Controller/NodeController.php b/core/modules/node/lib/Drupal/node/Controller/NodeController.php
index 4267101ffe1b3f39493730b144eedcb95d05ea3d..90e5899c86bf6f3e1e1c41a68c745d4937457ac6 100644
--- a/core/modules/node/lib/Drupal/node/Controller/NodeController.php
+++ b/core/modules/node/lib/Drupal/node/Controller/NodeController.php
@@ -127,7 +127,7 @@ public function page(NodeInterface $node) {
    *   The page title.
    */
   public function pageTitle(NodeInterface $node) {
-    return String::checkPlain($this->entityManager()->getTranslationFromContext($node)->label());
+    return String::checkPlain($node->label());
   }
 
   /**
diff --git a/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php b/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php
index 51da0371d34806ec6b9534397e2f3f0a394d7204..11eb3f31ecafbfa9574044585e2f98b5a7931665 100644
--- a/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php
+++ b/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php
@@ -9,7 +9,7 @@
 
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Entity\ContentEntityConfirmFormBase;
-use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -25,17 +25,24 @@ class NodeDeleteForm extends ContentEntityConfirmFormBase {
    */
   protected $urlGenerator;
 
+  /**
+   * The node type storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $nodeTypeStorage;
+
   /**
    * Constructs a NodeDeleteForm object.
    *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
    * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
    *   The URL generator.
+   * @param \Drupal\Core\Entity\EntityStorageControllerInterface $node_type_storage
+   *   The node type storage.
    */
-  public function __construct(EntityManagerInterface $entity_manager, UrlGeneratorInterface $url_generator) {
-    parent::__construct($entity_manager);
+  public function __construct(UrlGeneratorInterface $url_generator, EntityStorageControllerInterface $node_type_storage) {
     $this->urlGenerator = $url_generator;
+    $this->nodeTypeStorage = $node_type_storage;
   }
 
   /**
@@ -43,8 +50,8 @@ public function __construct(EntityManagerInterface $entity_manager, UrlGenerator
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('entity.manager'),
-      $container->get('url_generator')
+      $container->get('url_generator'),
+      $container->get('entity.manager')->getStorageController('node_type')
     );
   }
 
@@ -87,8 +94,7 @@ public function getConfirmText() {
   public function submit(array $form, array &$form_state) {
     $this->entity->delete();
     watchdog('content', '@type: deleted %title.', array('@type' => $this->entity->bundle(), '%title' => $this->entity->label()));
-    $node_type_storage = $this->entityManager->getStorageController('node_type');
-    $node_type = $node_type_storage->load($this->entity->bundle())->label();
+    $node_type = $this->nodeTypeStorage->load($this->entity->bundle())->label();
     drupal_set_message(t('@type %title has been deleted.', array('@type' => $node_type, '%title' => $this->entity->label())));
     Cache::invalidateTags(array('content' => TRUE));
     $form_state['redirect'] = '<front>';
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
index baa8d233dce622144b904b850d7a09540ca4dc0f..6a2608c1fe7551ecd0fa3a3f12f69168abe78d48 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php
@@ -72,7 +72,7 @@ protected function getFormSubmitAction(EntityInterface $entity) {
   /**
    * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::assertPublishedStatus().
    */
-  protected function doTestPublishedStatus() {
+  protected function assertPublishedStatus() {
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
     $path = $this->controller->getEditPath($entity);
     $languages = language_list();
@@ -104,7 +104,7 @@ protected function doTestPublishedStatus() {
   /**
    * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::assertAuthoringInfo().
    */
-  protected function doTestAuthoringInfo() {
+  protected function assertAuthoringInfo() {
     $entity = entity_load($this->entityType, $this->entityId, TRUE);
     $path = $this->controller->getEditPath($entity);
     $languages = language_list();
@@ -188,47 +188,4 @@ public function testDisabledBundle() {
     $this->assertEqual($enabledNode->id(), reset($rows)->entity_id);
   }
 
-  /**
-   * Tests that translations are rendered properly.
-   */
-  function testTranslationRendering() {
-    $default_langcode = $this->langcodes[0];
-    $values[$default_langcode] = $this->getNewEntityValues($default_langcode);
-    $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode);
-    $node = \Drupal::entityManager()->getStorageController($this->entityType)->load($this->entityId);
-    $node->setPromoted(TRUE);
-
-    // Create translations.
-    foreach (array_diff($this->langcodes, array($default_langcode)) as $langcode) {
-      $values[$langcode] = $this->getNewEntityValues($langcode);
-      $translation = $node->addTranslation($langcode, $values[$langcode]);
-      $translation->setPromoted(TRUE);
-    }
-    $node->save();
-
-    // Test that the frontpage view displays the correct translations.
-    \Drupal::moduleHandler()->install(array('views'), TRUE);
-    $this->rebuildContainer();
-    $this->doTestTranslations('node', $values);
-
-    // Test that the node page displays the correct translations.
-    $this->doTestTranslations('node/' . $node->id(), $values);
-  }
-
-  /**
-   * Tests that the given path dsiplays the correct translation values.
-   *
-   * @param string $path
-   *   The path to be tested.
-   * @param array $values
-   *   The translation values to be found.
-   */
-  protected function doTestTranslations($path, array $values) {
-    $languages = language_list();
-    foreach ($this->langcodes as $langcode) {
-      $this->drupalGet($path, array('language' => $languages[$langcode]));
-      $this->assertText($values[$langcode]['title'], format_string('The %langcode node translation is correctly displayed.', array('%langcode' => $langcode)));
-    }
-  }
-
 }
diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index 244a52b1b9f84d41b15698b0195ff6d54a7ccc8f..2f5d821be29302efbbe32619b1a39f77373d1ab8 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -129,11 +129,11 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
 
         case 'body':
         case 'summary':
-          $translation = \Drupal::entityManager()->getTranslationFromContext($node, $langcode, array('operation' => 'node_tokens'));
-          if (($items = $translation->get('body')) && !$items->isEmpty()) {
+          if (($items = $node->getTranslation($langcode)->get('body')) && !$items->isEmpty()) {
             $item = $items[0];
             $instance = field_info_instance('node', 'body', $node->getType());
-            $field_langcode = $translation->language()->id;
+            $field_langcode = field_language($node, 'body', $langcode);
+
             // If the summary was requested and is not empty, use it.
             if ($name == 'summary' && !empty($item->summary)) {
               $output = $sanitize ? $item->summary_processed : $item->summary;
diff --git a/core/modules/system/language.api.php b/core/modules/system/language.api.php
index de43f83bfb626df453cafe402ad375f619b8696f..cfa42ec5b96e923bd8b2797ca639585df791e493 100644
--- a/core/modules/system/language.api.php
+++ b/core/modules/system/language.api.php
@@ -151,6 +151,17 @@ function hook_language_negotiation_info_alter(array &$negotiation_info) {
   }
 }
 
+/**
+ * Perform alterations on the language fallback candidates.
+ *
+ * @param $fallback_candidates
+ *   An array of language codes whose order will determine the language fallback
+ *   order.
+ */
+function hook_language_fallback_candidates_alter(array &$fallback_candidates) {
+  $fallback_candidates = array_reverse($fallback_candidates);
+}
+
 /**
  * @} End of "addtogroup hooks".
  */
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php
index 7cbe7b5493fdf5740b9a399b00da28f70a894723..bd6d098c491957a35e1577cb7856e8e53cd9df49 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityManagerTest.php
@@ -34,7 +34,7 @@ public function testMethods() {
     $this->assertFalse($entity_manager->hasController('non_existent', 'non_existent'), 'A non existent entity type has no controller.');
 
     $this->assertFalse($entity_manager->hasController('entity_test', 'non_existent'), 'An existent entity type does not have a non existent controller.');
-    $this->assertFalse($entity_manager->hasController('entity_test_mulrev', 'view_builder'), 'The test entity does not have specified the view builder.');
+    $this->assertFalse($entity_manager->hasController('entity_test_mul', 'view_builder'), 'The test entity does not have specified the view builder.');
 
     $this->assertTrue($entity_manager->hasController('entity_test', 'storage'), 'The test entity has specified the controller class');
   }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
index bc0e1952d958643919e87521c60979e33dda77c1..e2b0d4f395a54c2d4c30921e038df39fee098cd2 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -10,7 +10,6 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\TypedData\TranslatableInterface;
 use Drupal\entity_test\Entity\EntityTestMulRev;
-use Drupal\Component\Utility\MapArray;
 
 /**
  * Tests entity translation.
@@ -84,7 +83,6 @@ function setUp() {
       $language = new Language(array(
         'id' => 'l' . $i,
         'name' => $this->randomString(),
-        'weight' => $i,
       ));
       $this->langcodes[$i] = $language->id;
       language_save($language);
@@ -495,69 +493,6 @@ function testEntityTranslationAPI() {
     $this->assertEqual($field->getLangcode(), $langcode2, 'Field object has the expected langcode.');
   }
 
-  /**
-   * Tests language fallback applied to field and entity translations.
-   */
-  function testLanguageFallback() {
-    $current_langcode = $this->container->get('language_manager')->getLanguage(Language::TYPE_CONTENT)->id;
-    $this->langcodes[] = $current_langcode;
-
-    $values = array();
-    foreach ($this->langcodes as $langcode) {
-      $values[$langcode]['name'] = $this->randomName();
-      $values[$langcode]['user_id'] = mt_rand(0, 127);
-    }
-
-    $default_langcode = $this->langcodes[0];
-    $langcode = $this->langcodes[1];
-    $langcode2 = $this->langcodes[2];
-
-    $entity_type = 'entity_test_mul';
-    $controller = $this->entityManager->getStorageController($entity_type);
-    $entity = $controller->create(array('langcode' => $default_langcode) + $values[$default_langcode]);
-    $entity->save();
-
-    $entity->addTranslation($langcode, $values[$langcode]);
-    $entity->save();
-
-    // Check that retrieveing the current translation works as expected.
-    $entity = $this->reloadEntity($entity);
-    $translation = $this->entityManager->getTranslationFromContext($entity, $langcode2);
-    $this->assertEqual($translation->language()->id, $default_langcode, 'The current translation language matches the expected one.');
-
-    // Check that language fallback respects language weight by default.
-    $languages = language_list();
-    $languages[$langcode]->weight = -1;
-    language_save($languages[$langcode]);
-    $translation = $this->entityManager->getTranslationFromContext($entity, $langcode2);
-    $this->assertEqual($translation->language()->id, $langcode, 'The current translation language matches the expected one.');
-
-    // Check that the current translation is properly returned.
-    $translation = $this->entityManager->getTranslationFromContext($entity);
-    $this->assertEqual($langcode, $translation->language()->id, 'The current translation language matches the topmost language fallback candidate.');
-    $entity->addTranslation($current_langcode, $values[$current_langcode]);
-    $translation = $this->entityManager->getTranslationFromContext($entity);
-    $this->assertEqual($current_langcode, $translation->language()->id, 'The current translation language matches the current language.');
-
-    // Check that if the entity has no translation no fallback is applied.
-    $entity2 = $controller->create(array('langcode' => $default_langcode));
-    $translation = $this->entityManager->getTranslationFromContext($entity2, $default_langcode);
-    $this->assertIdentical($entity2, $translation, 'When the entity has no translation no fallback is applied.');
-
-    // Checks that entity translations are rendered properly.
-    $controller = $this->entityManager->getViewBuilder($entity_type);
-    $build = $controller->view($entity);
-    $this->assertEqual($build['label']['#markup'], $values[$current_langcode]['name'], 'By default the entity is rendered in the current language.');
-    $langcodes = MapArray::copyValuesToKeys($this->langcodes);
-    // We have no translation for the $langcode2 langauge, hence the expected
-    // result is the topmost existing translation, that is $langcode.
-    $langcodes[$langcode2] = $langcode;
-    foreach ($langcodes as $desired => $expected) {
-      $build = $controller->view($entity, 'full', $desired);
-      $this->assertEqual($build['label']['#markup'], $values[$expected]['name'], 'The entity is rendered in the expected language.');
-    }
-  }
-
   /**
    * Check that field translatability is handled properly.
    */
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
index 69f1aabbe5364d80dc41f9f452486ab1528a3e80..8695b113898ef45b2943f31cab1447ce2cb86d9e 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
@@ -98,11 +98,8 @@ protected function init() {
   /**
    * Overrides Drupal\entity\Entity::label().
    */
-  public function label($langcode = NULL) {
+  public function label($langcode = Language::LANGCODE_DEFAULT) {
     $info = $this->entityInfo();
-    if (!isset($langcode)) {
-      $langcode = $this->activeLangcode;
-    }
     if (isset($info['entity_keys']['label']) && $info['entity_keys']['label'] == 'name') {
       return $this->getTranslation($langcode)->name->value;
     }
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
index 790732283c417b262dc48e6aa37b9f3cd9b6d94e..d3e0fb3a1b0a5071ce5679bf6147bec4b49d5162 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
@@ -19,7 +19,6 @@
  *   label = @Translation("Test entity - data table"),
  *   controllers = {
  *     "storage" = "Drupal\entity_test\EntityTestStorageController",
- *     "view_builder" = "Drupal\entity_test\EntityTestViewBuilder",
  *     "access" = "Drupal\entity_test\EntityTestAccessController",
  *     "form" = {
  *       "default" = "Drupal\entity_test\EntityTestFormController"
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php
index cec3c3cc3e15d1642909b76965d4159a6d1d17b4..18d3a6a4654e2ef31e0a9d9261f499bc19bdd0ae 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Form/TermDeleteForm.php
@@ -8,7 +8,7 @@
 namespace Drupal\taxonomy\Form;
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\taxonomy\VocabularyStorageControllerInterface;
 use Drupal\Core\Entity\ContentEntityConfirmFormBase;
 use Drupal\Core\Cache\Cache;
 
@@ -17,6 +17,32 @@
  */
 class TermDeleteForm extends ContentEntityConfirmFormBase {
 
+  /**
+   * The taxonomy vocabulary storage controller.
+   *
+   * @var \Drupal\taxonomy\VocabularyStorageControllerInterface
+   */
+  protected $vocabularyStorageController;
+
+  /**
+   * Constructs a new TermDelete object.
+   *
+   * @param \Drupal\taxonomy\VocabularyStorageControllerInterface $storage_controller
+   *   The Entity manager.
+   */
+  public function __construct(VocabularyStorageControllerInterface $storage_controller) {
+    $this->vocabularyStorageController = $storage_controller;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('entity.manager')->getStorageController('taxonomy_vocabulary')
+    );
+  }
+
   /**
    * {@inheritdoc}
    */
@@ -59,8 +85,7 @@ public function getConfirmText() {
    */
   public function submit(array $form, array &$form_state) {
     $this->entity->delete();
-    $storage_controller = $this->entityManager->getStorageController('taxonomy_vocabulary');
-    $vocabulary = $storage_controller->load($this->entity->bundle());
+    $vocabulary = $this->vocabularyStorageController->load($this->entity->bundle());
 
     // @todo Move to storage controller http://drupal.org/node/1988712
     taxonomy_check_vocabulary_hierarchy($vocabulary, array('tid' => $this->entity->id()));
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
index 0dbaf6322e39df3a36c4a212e6ed8ad3ac7028b3..8821b091990af5005527658b9152081c80d9065a 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php
@@ -10,7 +10,6 @@
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Entity\ContentEntityFormController;
-use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Language\Language;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -19,6 +18,13 @@
  */
 class TermFormController extends ContentEntityFormController {
 
+  /**
+   * The vocabulary storage.
+   *
+   * @var \Drupal\taxonomy\VocabularyStorageControllerInterface
+   */
+  protected $vocabStorage;
+
   /**
    * The config factory.
    *
@@ -29,13 +35,13 @@ class TermFormController extends ContentEntityFormController {
   /**
    * Constructs a new TermFormController.
    *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
+   * @param \Drupal\taxonomy\VocabularyStorageControllerInterface $vocab_storage
+   *   The vocabulary storage.
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
    *   The config factory.
    */
-  public function __construct(EntityManagerInterface $entity_manager, ConfigFactory $config_factory) {
-    parent::__construct($entity_manager);
+  public function __construct(VocabularyStorageControllerInterface $vocab_storage, ConfigFactory $config_factory) {
+    $this->vocabStorage = $vocab_storage;
     $this->configFactory = $config_factory;
   }
 
@@ -44,7 +50,7 @@ public function __construct(EntityManagerInterface $entity_manager, ConfigFactor
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('entity.manager'),
+      $container->get('entity.manager')->getStorageController('taxonomy_vocabulary'),
       $container->get('config.factory')
     );
   }
@@ -54,8 +60,7 @@ public static function create(ContainerInterface $container) {
    */
   public function form(array $form, array &$form_state) {
     $term = $this->entity;
-    $vocab_storage = $this->entityManager->getStorageController('taxonomy_vocabulary');
-    $vocabulary = $vocab_storage->load($term->bundle());
+    $vocabulary = $this->vocabStorage->load($term->bundle());
 
     $parent = array_keys(taxonomy_term_load_parents($term->id()));
     $form_state['taxonomy']['parent'] = $parent;
diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php
index fdb39ae8f5e610315793a3f5a5933b114d7815e3..714011222c02c5863d2a839f7cfba3e64619ea5f 100644
--- a/core/modules/user/lib/Drupal/user/AccountFormController.php
+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -8,7 +8,6 @@
 namespace Drupal\user;
 
 use Drupal\Core\Entity\ContentEntityFormController;
-use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Language\LanguageManager;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -28,13 +27,10 @@ abstract class AccountFormController extends ContentEntityFormController {
   /**
    * Constructs a new EntityFormController object.
    *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
    * @param \Drupal\Core\Language\LanguageManager $language_manager
    *   The language manager.
    */
-  public function __construct(EntityManagerInterface $entity_manager, LanguageManager $language_manager) {
-    parent::__construct($entity_manager);
+  public function __construct(LanguageManager $language_manager) {
     $this->languageManager = $language_manager;
   }
 
@@ -43,7 +39,6 @@ public function __construct(EntityManagerInterface $entity_manager, LanguageMana
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('entity.manager'),
       $container->get('language_manager')
     );
   }
diff --git a/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php b/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php
index 59d6145f458fec26dc2bf2887beae016c7c31853..973c84e97fdb19329da10fd7aac5aad0acb10d31 100644
--- a/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php
+++ b/core/modules/user/lib/Drupal/user/Form/UserCancelForm.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\Config\ConfigFactory;
 use Drupal\Core\Entity\ContentEntityConfirmFormBase;
-use Drupal\Core\Entity\EntityManagerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -43,11 +42,8 @@ class UserCancelForm extends ContentEntityConfirmFormBase {
    *
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
    *   The config factory.
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
    */
-  public function __construct(EntityManagerInterface $entity_manager, ConfigFactory $config_factory) {
-    parent::__construct($entity_manager);
+  public function __construct(ConfigFactory $config_factory) {
     $this->configFactory = $config_factory;
   }
 
@@ -56,7 +52,6 @@ public function __construct(EntityManagerInterface $entity_manager, ConfigFactor
    */
   public static function create(ContainerInterface $container) {
     return new static(
-      $container->get('entity.manager'),
       $container->get('config.factory')
     );
   }