diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
index 19f7e4f..911de6c 100644
--- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
@@ -14,7 +14,6 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\DatabaseStorageController;
 use Drupal\Core\Entity\EntityStorageException;
-use Drupal\Core\TypedData\TranslatableInterface;
 use Drupal\Component\Uuid\Uuid;
 use Drupal\Core\Database\Connection;
 
@@ -493,20 +492,20 @@ protected function savePropertyData(EntityInterface $entity) {
    * Checks translation statuses and invoke the related hooks if needed.
    *
    * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity being saved.
    */
   function notifyTranslationChanges(EntityInterface $entity) {
-    // Notify modules of translation creation/removal.
-    foreach ($entity->getTranslationLanguages(FALSE, TRUE) as $langcode => $language) {
-      $translation = $entity->getTranslation($langcode);
-
-      switch ($translation->getTranslationStatus()) {
-        case TranslatableInterface::TRANSLATION_CREATED:
-          $this->invokeHook('translation_insert', $translation);
-          break;
-
-        case TranslatableInterface::TRANSLATION_REMOVED:
-          $this->invokeHook('translation_delete', $translation);
-          break;
+    $translations = $entity->getTranslationLanguages(FALSE);
+    $original_translations = $entity->original->getTranslationLanguages(FALSE);
+    $all_translations = array_keys($translations + $original_translations);
+
+    // Notify modules of translation insertion/deletion.
+    foreach ($all_translations as $langcode) {
+      if (isset($translations[$langcode]) && !isset($original_translations[$langcode])) {
+        $this->invokeHook('translation_insert', $entity->getTranslation($langcode));
+      }
+      elseif (!isset($translations[$langcode]) && isset($original_translations[$langcode])) {
+        $this->invokeHook('translation_delete', $entity->getTranslation($langcode));
       }
     }
   }
diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index 48d5a53..5fad856 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -318,7 +318,7 @@ public function translations() {
   /**
    * Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslationLanguages().
    */
-  public function getTranslationLanguages($include_default = TRUE, $include_removed = FALSE) {
+  public function getTranslationLanguages($include_default = TRUE) {
     // @todo: Replace by EntityNG implementation once all entity types have been
     // converted to use the entity field API.
     $default_language = $this->language();
@@ -593,14 +593,14 @@ public function preSaveRevision(EntityStorageControllerInterface $storage_contro
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::getOriginal().
+   * {@inheritdoc}
    */
   public function getOriginal() {
     return $this->getTranslation(Language::LANGCODE_DEFAULT);
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::hasTranslation().
+   * {@inheritdoc}
    */
   public function hasTranslation($langcode) {
     $translations = $this->getTranslationLanguages();
@@ -608,24 +608,17 @@ public function hasTranslation($langcode) {
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::addTranslation().
+   * {@inheritdoc}
    */
   public function addTranslation($langcode, array $values = array()) {}
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::removeTranslation().
+   * {@inheritdoc}
    */
   public function removeTranslation($langcode) {}
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslationStatus().
-   */
-  public function getTranslationStatus() {
-    return TranslatableInterface::TRANSLATION_EXISTING;
-  }
-
-  /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::initTranslation().
+   * {@inheritdoc}
    */
   public function initTranslation($langcode) {}
 
diff --git a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
index 85335c6..b84634a 100644
--- a/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
+++ b/core/lib/Drupal/Core/Entity/EntityBCDecorator.php
@@ -417,8 +417,8 @@ public function language() {
   /**
    * Forwards the call to the decorated entity.
    */
-  public function getTranslationLanguages($include_default = TRUE, $include_removed = FALSE) {
-    return $this->decorated->getTranslationLanguages($include_default, $include_removed);
+  public function getTranslationLanguages($include_default = TRUE) {
+    return $this->decorated->getTranslationLanguages($include_default);
   }
 
   /**
@@ -621,13 +621,6 @@ public function removeTranslation($langcode) {
   /**
    * Forwards the call to the decorated entity.
    */
-  public function getTranslationStatus() {
-   return $this->decorated->getTranslationStatus();
-  }
-
-  /**
-   * Forwards the call to the decorated entity.
-   */
   public function initTranslation($langcode) {
     $this->decorated->initTranslation($langcode);
   }
diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php
index ea669f7..a4ef19f 100644
--- a/core/lib/Drupal/Core/Entity/EntityNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityNG.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\Language\Language;
 use Drupal\Core\Session\AccountInterface;
-use Drupal\Core\TypedData\TranslatableInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 use ArrayIterator;
 use InvalidArgumentException;
@@ -28,6 +27,21 @@
 class EntityNG extends Entity {
 
   /**
+   * Status code indentifying a removed translation.
+   */
+  protected static $TRANSLATION_REMOVED = 0;
+
+  /**
+   * Status code indentifying an existing translation.
+   */
+  protected static $TRANSLATION_EXISTING = 1;
+
+  /**
+   * Status code indentifying a newly created translation.
+   */
+  protected static $TRANSLATION_CREATED = 2;
+
+  /**
    * Local cache holding the value of the bundle field.
    *
    * @var string
@@ -111,9 +125,9 @@ class EntityNG extends Entity {
   /**
    * A flag indicating whether a translation object is being initialized.
    *
-   * @var boolean
+   * @var bool
    */
-  protected $translationInit = FALSE;
+  protected $translationInitialize = FALSE;
 
   /**
    * Overrides Entity::__construct().
@@ -133,7 +147,7 @@ public function __construct(array $values, $entity_type, $bundle = FALSE, $trans
 
     // Initialize translations. Ensure we have at least an entry for the entity
     // original language.
-    $data = array('status' => TranslatableInterface::TRANSLATION_EXISTING);
+    $data = array('status' => self::$TRANSLATION_EXISTING);
     $this->translations[Language::LANGCODE_DEFAULT] = $data;
     if ($translations) {
       $default_langcode = $this->language()->langcode;
@@ -178,6 +192,9 @@ protected function clearTranslationCache() {
    */
   public function __wakeup() {
     $this->init();
+    // @todo This should be done before serializing the entity, but we would
+    //   need to provide the full list of data to be serialized. See the
+    //   dedicated issue at https://drupal.org/node/2027795.
     $this->clearTranslationCache();
   }
 
@@ -261,7 +278,6 @@ protected function uriPlaceholderReplacements() {
    * Implements \Drupal\Core\TypedData\ComplexDataInterface::get().
    */
   public function get($property_name) {
-    $this->checkTranslationStatus();
     if (!isset($this->fields[$property_name][$this->activeLangcode])) {
       return $this->getTranslatedField($property_name, $this->activeLangcode);
     }
@@ -274,6 +290,7 @@ public function get($property_name) {
    * @return \Drupal\Core\Entity\Field\FieldInterface
    */
   protected function getTranslatedField($property_name, $langcode) {
+    $this->checkTranslationStatus();
     // Populate $this->fields to speed-up further look-ups and to keep track of
     // fields objects, possibly holding changes to field values.
     if (!isset($this->fields[$property_name][$langcode])) {
@@ -291,6 +308,13 @@ protected function getTranslatedField($property_name, $langcode) {
         if (isset($this->values[$property_name][$langcode])) {
           $value = $this->values[$property_name][$langcode];
         }
+        // @todo Remove this once the BC decorator is gone.
+        elseif ($property_name != 'langcode' && $langcode == Language::LANGCODE_DEFAULT) {
+          $default_langcode = $this->language()->langcode;
+          if (isset($this->values[$property_name][$default_langcode])) {
+            $value = $this->values[$property_name][$default_langcode];
+          }
+        }
         $this->fields[$property_name][$langcode] = \Drupal::typedData()->getPropertyInstance($this, $property_name, $value);
       }
     }
@@ -386,7 +410,7 @@ public function isEmpty() {
   }
 
   /**
-   * @inheritdoc
+   * {@inheritdoc}
    */
   public function access($operation = 'view', AccountInterface $account = NULL) {
     return \Drupal::entityManager()
@@ -395,7 +419,7 @@ public function access($operation = 'view', AccountInterface $account = NULL) {
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::language().
+   * {@inheritdoc}
    */
   public function language() {
     if ($this->activeLangcode != Language::LANGCODE_DEFAULT) {
@@ -404,7 +428,7 @@ public function language() {
         return $languages[$this->activeLangcode];
       }
     }
-    return $this->getOriginalLanguage();
+    return $this->getDefaultLanguage();
   }
 
   /**
@@ -413,7 +437,7 @@ public function language() {
    * @return \Drupal\Core\Language\Language
    *   The entity language object.
    */
-  protected function getOriginalLanguage() {
+  protected function getDefaultLanguage() {
     // Keep a local cache of the language object and clear it if the langcode
     // gets changed, see EntityNG::onChange().
     if (!isset($this->language)) {
@@ -448,7 +472,7 @@ public function onChange($property_name) {
   public function getTranslation($langcode) {
     // Ensure we always use the default language code when dealing with the
     // original entity language.
-    if ($langcode != Language::LANGCODE_DEFAULT && $langcode == $this->getOriginalLanguage()->langcode) {
+    if ($langcode != Language::LANGCODE_DEFAULT && $langcode == $this->getDefaultLanguage()->langcode) {
       $langcode = Language::LANGCODE_DEFAULT;
     }
 
@@ -461,43 +485,46 @@ public function getTranslation($langcode) {
     // If we already have a translation object for the specified language we can
     // just return it.
     if (isset($this->translations[$langcode]['entity'])) {
-      return $this->translations[$langcode]['entity'];
-    }
-
-    // If the requested translation is valid, we instantiate a new translation
-    // object being a clone of the current one but with the specified language
-    // as active language. Before cloning we specify we are initializing a
-    // translation object to perform a shallow clone, in fact all the field data
-    // structures need to be shared among the translation objects to ensure all
-    // of them deal with fresh data.
-    if (isset($this->translations[$langcode])) {
-      $this->translationInit = TRUE;
-      $translation = clone $this;
-      unset($translation->bcEntity);
-      $translation->activeLangcode = $langcode;
-      // Ensure that changes to fields, values and translations are propagated
-      // to all the translation objects.
-      // @todo Consider converting these to ArrayObject.
-      $translation->values = &$this->values;
-      $translation->fields = &$this->fields;
-      $translation->translations = &$this->translations;
-      $translation->translationInit = FALSE;
-      $this->translations[$langcode]['entity'] = $translation;
-      $this->translationInit = FALSE;
-      return $translation;
-    }
-
-    // If we were given a valid language and there is no translation for it, we
-    // return a new one.
-    $languages = language_list();
-    if (isset($languages[$langcode])) {
-      // If the entity language is not a configured language we fall back to the
-      // entity itself, since in this case it cannot have translations.
-      return isset($languages[$this->getOriginalLanguage()->langcode]) ? $this->addTranslation($langcode) : $this;
-    }
-
-    // TODO Do we want to return $this instead?
-    throw new InvalidArgumentException("Invalid '$langcode' specified.");
+      $translation = $this->translations[$langcode]['entity'];
+    }
+    else {
+      // If the requested translation is valid, we instantiate a new translation
+      // object being a clone of the current one but with the specified language
+      // as active language. Before cloning we specify we are initializing a
+      // translation object to perform a shallow clone, in fact all the field
+      // data structures need to be shared among the translation objects to
+      // ensure all of them deal with fresh data.
+      if (isset($this->translations[$langcode])) {
+        $this->translationInitialize = TRUE;
+        $translation = clone $this;
+        $translation->activeLangcode = $langcode;
+        // Ensure that changes to fields, values and translations are propagated
+        // to all the translation objects.
+        // @todo Consider converting these to ArrayObject.
+        $translation->values = &$this->values;
+        $translation->fields = &$this->fields;
+        $translation->translations = &$this->translations;
+        $translation->translationInitialize = FALSE;
+        $this->translations[$langcode]['entity'] = $translation;
+        $this->translationInitialize = FALSE;
+      }
+      else {
+        // If we were given a valid language and there is no translation for it,
+        // we return a new one.
+        $languages = language_list();
+        if (isset($languages[$langcode])) {
+          // If the entity language is not a configured language we fall back to
+          // the entity itself, since in this case it cannot have translations.
+          $translation = isset($languages[$this->getDefaultLanguage()->langcode]) ? $this->addTranslation($langcode) : $this;
+        }
+      }
+    }
+
+    if (empty($translation)) {
+      throw new \InvalidArgumentException("Invalid '$langcode' specified.");
+    }
+
+    return $translation;
   }
 
   /**
@@ -519,16 +546,18 @@ public function addTranslation($langcode, array $values = array()) {
     // Instantiate a new empty entity so default values will be populated in the
     // specified language.
     $info = $this->entityInfo();
-    // @todo Use the actual translation language once the BC decorator is gone.
-    $default_values = array($info['entity_keys']['bundle'] => $this->bundle, 'langcode' => Language::LANGCODE_NOT_SPECIFIED);
-    $entity = entity_create($this->entityType(), $default_values);
+    $default_values = array($info['entity_keys']['bundle'] => $this->bundle, 'langcode' => $langcode);
+    $entity = \Drupal::entityManager()
+      ->getStorageController($this->entityType())
+      ->create($default_values);
+
     foreach ($entity as $name => $field) {
       if (!isset($values[$name]) && !$field->isEmpty()) {
         $values[$name] = $field->value;
       }
     }
 
-    $this->translations[$langcode]['status'] = self::TRANSLATION_CREATED;
+    $this->translations[$langcode]['status'] = self::$TRANSLATION_CREATED;
     $translation = $this->getTranslation($langcode);
     $definitions = $translation->getPropertyDefinitions();
 
@@ -545,28 +574,27 @@ public function addTranslation($langcode, array $values = array()) {
    * {@inheritdoc}
    */
   public function removeTranslation($langcode) {
-    $translation = $this->getTranslation($langcode);
-    foreach ($translation->getPropertyDefinitions() as $name => $definition) {
-      if (!empty($definition['translatable'])) {
-        $translation->$name = array();
+    if (isset($this->translations[$langcode]) && $langcode != Language::LANGCODE_DEFAULT && $langcode != $this->getDefaultLanguage()->langcode) {
+      foreach ($this->getPropertyDefinitions() as $name => $definition) {
+        if (!empty($definition['translatable'])) {
+          unset($this->values[$langcode]);
+          unset($this->fields[$langcode]);
+        }
       }
+      $this->translations[$langcode]['status'] = self::$TRANSLATION_REMOVED;
+    }
+    else {
+      $message = 'The specified translation (@langcode) cannot be removed.';
+      throw new \InvalidArgumentException(format_string($message, array('@langcode' => $langcode)));
     }
-    $this->translations[$langcode]['status'] = self::TRANSLATION_REMOVED;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getTranslationStatus() {
-    return $this->translations[$this->activeLangcode]['status'];
   }
 
   /**
    * {@inheritdoc}
    */
   public function initTranslation($langcode) {
-    if ($langcode != Language::LANGCODE_DEFAULT && $langcode != $this->getOriginalLanguage()->langcode) {
-      $this->translations[$langcode]['status'] = self::TRANSLATION_EXISTING;
+    if ($langcode != Language::LANGCODE_DEFAULT && $langcode != $this->getDefaultLanguage()->langcode) {
+      $this->translations[$langcode]['status'] = self::$TRANSLATION_EXISTING;
     }
   }
 
@@ -577,32 +605,26 @@ public function initTranslation($langcode) {
    * soon as the related translation has been removed. Any attempt to access
    * invalid data causes an exception to be thrown.
    *
-   * @return boolean
+   * @return bool
    *   TRUE if the translation object has a valid status.
    */
   protected function checkTranslationStatus() {
-    if ($this->translations[$this->activeLangcode]['status'] == self::TRANSLATION_REMOVED) {
-      // TODO Use a more specific exception.
-      throw new \Exception('The entity object refers to a removed translation and cannot be manipulated.');
+    if ($this->translations[$this->activeLangcode]['status'] == self::$TRANSLATION_REMOVED) {
+      $message = 'The entity object refers to a removed translation (@langcode) and cannot be manipulated.';
+      throw new \InvalidArgumentException(format_string($message, array('@langcode' => $this->activeLangcode)));
     }
     return TRUE;
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslationLanguages().
+   * {@inheritdoc}
    */
-  public function getTranslationLanguages($include_default = TRUE, $include_removed = FALSE) {
-    if (!$include_removed) {
-      $translations = array_filter($this->translations, function($translation) { return $translation['status']; });
-    }
-    else {
-      $translations = $this->translations;
-    }
-
+  public function getTranslationLanguages($include_default = TRUE) {
+    $translations = array_filter($this->translations, function($translation) { return $translation['status']; });
     unset($translations[Language::LANGCODE_DEFAULT]);
 
     if ($include_default) {
-      $langcode = $this->getOriginalLanguage()->langcode;
+      $langcode = $this->getDefaultLanguage()->langcode;
       $translations[$langcode] = TRUE;
     }
 
@@ -655,7 +677,6 @@ public function updateOriginalValues() {
    * For compatibility mode to work this must return a reference.
    */
   public function &__get($name) {
-    $this->checkTranslationStatus();
     // If this is an entity field, handle it accordingly. We first check whether
     // a field object has been already created. If not, we create one.
     if (isset($this->fields[$name][$this->activeLangcode])) {
@@ -688,7 +709,6 @@ public function &__get($name) {
    * Uses default language always.
    */
   public function __set($name, $value) {
-    $this->checkTranslationStatus();
     // Support setting values via property objects.
     if ($value instanceof TypedDataInterface && !$value instanceof EntityInterface) {
       $value = $value->getValue();
@@ -737,6 +757,7 @@ public function __unset($name) {
    */
   public function createDuplicate() {
     $this->checkTranslationStatus();
+
     $duplicate = clone $this;
     $entity_info = $this->entityInfo();
     $duplicate->{$entity_info['entity_keys']['id']}->value = NULL;
@@ -760,19 +781,16 @@ public function createDuplicate() {
   public function __clone() {
     // Avoid deep-cloning when we are initializing a translation object, since
     // it will represent the same entity, only with a different active language.
-    if ($this->translationInit) {
-      return;
-    }
-
-    foreach ($this->fields as $name => $properties) {
-      foreach ($properties as $langcode => $property) {
-        $this->fields[$name][$langcode] = clone $property;
-        $this->fields[$name][$langcode]->setContext($name, $this);
+    if (!$this->translationInitialize) {
+      foreach ($this->fields as $name => $properties) {
+        foreach ($properties as $langcode => $property) {
+          $this->fields[$name][$langcode] = clone $property;
+          $this->fields[$name][$langcode]->setContext($name, $this);
+        }
       }
+      $this->clearTranslationCache();
     }
-
     $this->bcEntity = NULL;
-    $this->clearTranslationCache();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
index d3da690..5104271 100644
--- a/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
+++ b/core/lib/Drupal/Core/TypedData/TranslatableInterface.php
@@ -13,21 +13,6 @@
 interface TranslatableInterface {
 
   /**
-   * Status code indentifying a removed translation.
-   */
-  const TRANSLATION_REMOVED = 0;
-
-  /**
-   * Status code indentifying an existing translation.
-   */
-  const TRANSLATION_EXISTING = 1;
-
-  /**
-   * Status code indentifying a newly created translation.
-   */
-  const TRANSLATION_CREATED = 2;
-
-  /**
    * Returns the default language.
    *
    * @return \Drupal\Core\Language\Language
@@ -41,14 +26,11 @@ public function language();
    * @param bool $include_default
    *   (optional) Whether the default language should be included. Defaults to
    *   TRUE.
-   * @param bool $include_removed
-   *   Whether languages referring to removed translations should be included.
-   *   Defaults to FALSE.
    *
    * @return
    *   An array of language objects, keyed by language codes.
    */
-  public function getTranslationLanguages($include_default = TRUE, $include_removed = FALSE);
+  public function getTranslationLanguages($include_default = TRUE);
 
   /**
    * Gets a translation of the data.
@@ -82,6 +64,7 @@ public function getOriginal();
    *   The language code identifiying the translation.
    *
    * @return bool
+   *   TRUE if the translation exists, FALSE otherwise.
   */
   public function hasTranslation($langcode);
 
@@ -102,24 +85,18 @@ public function addTranslation($langcode, array $values = array());
    * Removes the translation identified by the given language code.
    *
    * @param string $langcode
+   *   The language code identifying the translation to be removed.
    */
   public function removeTranslation($langcode);
 
   /**
-   * Returns the current status of the entity translation object.
-   *
-   * @return integer
-   *   A translation status code as defined in TranslatableInterface.
-   */
-  public function getTranslationStatus();
-
-  /**
    * Marks the translation identified by the given language code as existing.
    *
    * @todo Remove this as soon as translation metadata have been converted to
    *    regular fields.
    *
    * @param string $langcode
+   *   The language code identifying the translation to be initialized.
    */
   public function initTranslation($langcode);
 
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index d73991c..8c5a0ce 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -235,9 +235,7 @@ function field_system_info_alter(&$info, $file, $type) {
 function field_entity_create(EntityInterface $entity) {
   $info = $entity->entityInfo();
   if (!empty($info['fieldable'])) {
-    foreach ($entity->getTranslationLanguages() as $langcode => $language) {
-      field_populate_default_values($entity, $langcode);
-    }
+    field_populate_default_values($entity, $entity->language()->langcode);
   }
 }
 
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 a44c5c9..6122822 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -9,7 +9,6 @@
 
 use Drupal\Core\Language\Language;
 use Drupal\Core\TypedData\TranslatableInterface;
-use Exception;
 use InvalidArgumentException;
 
 /**
@@ -32,8 +31,6 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $this->state = $this->container->get('state');
-
     $this->installSchema('system', 'variable');
     $this->installSchema('language', 'language');
     $this->installSchema('entity_test', array(
@@ -370,14 +367,9 @@ function testEntityTranslationAPI() {
     $this->assertEqual($hooks['entity_translation_insert'], $langcode, 'The generic entity translation insertion hook has fired.');
     $this->assertEqual($hooks['entity_test_mul_translation_insert'], $langcode, 'The entity-type-specific entity translation insertion hook has fired.');
 
-    // Check that after loading an entity all the translations have the expected
-    // status.
+    // Check that after loading an entity the language is the default one.
     $entity = $this->reloadEntity($entity);
     $this->assertEqual($entity->language()->langcode, $default_langcode, 'The loaded entity is the original one.');
-    foreach ($entity->getTranslationLanguages() as $language) {
-      $translation = $entity->getTranslation($language->langcode);
-      $this->assertEqual($translation->getTranslationStatus(), TranslatableInterface::TRANSLATION_EXISTING, 'The translations are loaded with the correct status.');
-    }
 
     // Add another translation and check that everything works as expected. A
     // new translation object can be obtained also by just specifying a valid
@@ -403,7 +395,7 @@ function testEntityTranslationAPI() {
         $translation->{$method}('name', $this->randomName());
         $this->fail($message);
       }
-      catch (Exception $e) {
+      catch (\Exception $e) {
         $this->pass($message);
       }
     }
@@ -414,6 +406,29 @@ function testEntityTranslationAPI() {
     $hooks = $this->getHooksInfo();
     $this->assertEqual($hooks['entity_translation_delete'], $langcode2, 'The generic entity translation deletion hook has fired.');
     $this->assertEqual($hooks['entity_test_mul_translation_delete'], $langcode2, 'The entity-type-specific entity translation deletion hook has fired.');
+    $entity = $this->reloadEntity($entity);
+    $this->assertFalse($entity->hasTranslation($langcode2), 'The translation does not appear among available translations after saving the entity.');
+
+    // Check that removing an invalid translation causes an exception to be
+    // thrown.
+    foreach (array($default_langcode, Language::LANGCODE_DEFAULT, $this->randomName()) as $invalid_langcode) {
+      $message = format_string('Removing an invalid translation (@langcode) causes an exception to be thrown.', array('@langcode' => $invalid_langcode));
+      try {
+        $entity->removeTranslation($invalid_langcode);
+        $this->fail($message);
+      }
+      catch (\Exception $e) {
+        $this->pass($message);
+      }
+    }
+
+    // Check that hooks are fired only when actually storing data.
+    $entity = $this->reloadEntity($entity);
+    $entity->addTranslation($langcode2);
+    $entity->removeTranslation($langcode2);
+    $entity->save();
+    $hooks = $this->getHooksInfo();
+    $this->assertFalse($hooks, 'No hooks are run when adding and removing a translation without storing it.');
 
     // Verify that entity serialization does not cause stale references to be
     // left around.
@@ -436,6 +451,16 @@ function testEntityTranslationAPI() {
     $cloned = clone $entity;
     $translation = $cloned->getTranslation($langcode);
     $this->assertNotEqual($entity, $translation->getOriginal(), 'A cloned entity object has no reference to the original one.');
+
+    // Check that per-language defaults are properly populated.
+    $entity = $this->reloadEntity($entity);
+    $instance_id = implode('.', array($entity->entityType(), $entity->bundle(), $this->field_name));
+    $instances = $this->entityManager->getStorageController('field_instance')->load(array($instance_id));
+    $instance = reset($instances);
+    $instance['default_value_function'] = 'entity_test_field_default_value';
+    $instance->save();
+    $translation = $entity->addTranslation($langcode2);
+    $this->assertEqual($translation->get($this->field_name)->value, $this->field_name . '_' . $langcode2, 'Language-aware default values correctly populated.');
   }
 
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
index 0676ad4..9ac9cff 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
@@ -38,7 +38,10 @@
 
   public function setUp() {
     parent::setUp();
+
     $this->entityManager = $this->container->get('plugin.manager.entity');
+    $this->state = $this->container->get('state');
+
     $this->installSchema('user', 'users');
     $this->installSchema('system', 'sequences');
     $this->installSchema('entity_test', 'entity_test');
@@ -96,7 +99,7 @@ protected function reloadEntity(EntityInterface $entity) {
   }
 
   /**
-   * Returns the entity_test hook invocation info recorded through the state service.
+   * Returns the entity_test hook invocation info.
    *
    * @return array
    *   An associative array of arbitrary hook data keyed by hook name.
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 5b616ab..03dc4dc 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -7,6 +7,8 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\entity\Plugin\Core\Entity\EntityFormDisplay;
+use Drupal\field\Plugin\Core\Entity\Field;
+use Drupal\field\Plugin\Core\Entity\FieldInstance;
 
 /**
  * Filter that limits test entity list to revisable ones.
@@ -462,11 +464,26 @@ function entity_test_entity_test_mul_translation_delete(EntityInterface $transla
 }
 
 /**
+ * Field default value callback.
+ *
+ * @param \Drupal\Core\Entity\EntityInterface $entity
+ *   The entity the field belongs to.
+ * @param \Drupal\field\Plugin\Core\Entity\Field $field
+ *   The field for which default values should be provided.
+ * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
+ *   The field instance for which default values should be provided.
+ * @param string $langcode
+ *   The field language code to fill-in with the default value.
+ */
+function entity_test_field_default_value(EntityInterface $entity, Field $field, FieldInstance $instance, $langcode) {
+  return array(array('value' => $field['field_name'] . '_' . $langcode));
+}
+
+/**
  * Helper function to be used to record hook invocations.
  *
  * @param string $hook
  *   The hook name.
- *
  * @param mixed $data
  *   Arbitrary data associated to the hook invocation.
  */
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
index adf8749..48df936 100644
--- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
+++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
@@ -931,8 +931,8 @@ public function getTranslation($langcode) {
   /**
    * Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslationLanguages().
    */
-  public function getTranslationLanguages($include_default = TRUE, $include_removed = FALSE) {
-    return $this->storage->getTranslationLanguages($include_default, $include_removed);
+  public function getTranslationLanguages($include_default = TRUE) {
+    return $this->storage->getTranslationLanguages($include_default);
   }
 
   /**
@@ -1048,42 +1048,35 @@ public function isTranslatable() {
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::getOriginal().
+   * {@inheritdoc}
    */
   public function getOriginal() {
     return $this->storage->getOriginal();
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::hasTranslation().
+   * {@inheritdoc}
    */
   public function hasTranslation($langcode) {
     return $this->storage->hasTranslation($langcode);
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::addTranslation().
+   * {@inheritdoc}
    */
   public function addTranslation($langcode, array $values = array()) {
     return $this->storage->addTranslation($langcode, $values);
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::removeTranslation().
+   * {@inheritdoc}
    */
   public function removeTranslation($langcode) {
     $this->storage->removeTranslation($langcode);
   }
 
   /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslationStatus().
-   */
-  public function getTranslationStatus() {
-    return $this->storage->getTranslationStatus();
-  }
-
-  /**
-   * Implements \Drupal\Core\TypedData\TranslatableInterface::getTranslationStatus().
+   * {@inheritdoc}
    */
   public function initTranslation($langcode) {
     $this->storage->initTranslation($langcode);
