diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index f7d6da0..bf61ad7 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -248,13 +248,21 @@ public function getTranslation($langcode, $strict = TRUE) {
    * Returns the languages the entity is translated to.
    *
    * @todo: Remove once all entity types implement the entity field API. This
-   * is deprecated by
-   * TranslatableInterface::getTranslationLanguages().
+   * is deprecated by TranslatableInterface::getTranslationLanguages().
    */
   public function translations() {
-    $default_language = $this->language();
-    $languages = array($default_language->langcode => $default_language);
+    return $this->getTranslationLanguages(FALSE);
+  }
+
+  /**
+   * Implements TranslatableInterface::getTranslationLanguages().
+   */
+  public function getTranslationLanguages($include_default = TRUE) {
+    // @todo: Replace by EntityNG implementation once all entity types have been
+    // converted to use the entity field API.
+    $languages = array();
     $entity_info = $this->entityInfo();
+
     if ($entity_info['fieldable']) {
       // Go through translatable properties and determine all languages for
       // which translated values are available.
@@ -268,15 +276,12 @@ public function translations() {
       }
       $languages = array_intersect_key(language_list(LANGUAGE_ALL), $languages);
     }
-    return $languages;
-  }
 
-  /**
-   * Implements TranslatableInterface::getTranslationLanguages().
-   */
-  public function getTranslationLanguages($include_default = TRUE) {
-    // @todo: Replace by EntityNG implementation once all entity types have been
-    // converted to use the entity field API.
+    if (empty($include_default)) {
+      unset($languages[$this->language()->langcode]);
+    }
+
+    return $languages;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php
index c866a34..33aef2d 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormController.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormController.php
@@ -210,7 +210,7 @@ public function delete(array $form, array &$form_state) {
    */
   public function getFormLangcode(array $form_state) {
     $entity = $this->getEntity($form_state);
-    $translations = $entity->translations();
+    $translations = $entity->getTranslationLanguages();
 
     if (!empty($form_state['langcode'])) {
       $langcode = $form_state['langcode'];
diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
index d06614d..812a192 100644
--- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php
@@ -64,14 +64,19 @@ public function buildEntity(array $form, array &$form_state) {
     // without changing existing entity properties that are not being edited by
     // this form. Copying field values must be done using field_attach_submit().
     $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values'];
+    $translation = $entity->getTranslation($this->getFormLangcode($form_state), FALSE);
+    $definitions = $translation->getPropertyDefinitions();
     foreach ($values_excluding_fields as $key => $value) {
-      $entity->$key = $value;
+      if (isset($definitions[$key])) {
+        $translation->$key = $value;
+      }
     }
 
-    // Invoke all specified builders for copying form values to entity properties.
+    // Invoke all specified builders for copying form values to entity
+    // properties.
     if (isset($form['#entity_builders'])) {
       foreach ($form['#entity_builders'] as $function) {
-        $function($entity_type, $entity, $form, $form_state);
+        call_user_func_array($function, array($entity_type, $entity, &$form, &$form_state));
       }
     }
 
diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php
index 1dc938a..8a2e050 100644
--- a/core/lib/Drupal/Core/Entity/EntityNG.php
+++ b/core/lib/Drupal/Core/Entity/EntityNG.php
@@ -269,21 +269,13 @@ public function getTranslationLanguages($include_default = TRUE) {
       $translations[$this->language()->langcode] = TRUE;
     }
 
-    // Now get languages based upon translation langcodes.
-    $languages = array_intersect_key(language_list(LANGUAGE_ALL), $translations);
+    // Now get languages based upon translation langcodes. Empty languages must
+    // be filtered out as they concern empty/unset properties.
+    $languages = array_intersect_key(language_list(LANGUAGE_ALL), array_filter($translations));
     return $languages;
   }
 
   /**
-   * Overrides Entity::translations().
-   *
-   * @todo: Remove once Entity::translations() gets removed.
-   */
-  public function translations() {
-    return $this->getTranslationLanguages(FALSE);
-  }
-
-  /**
    * Enables or disable the compatibility mode.
    *
    * @param bool $enabled
diff --git a/core/modules/node/lib/Drupal/node/NodeTranslationController.php b/core/modules/node/lib/Drupal/node/NodeTranslationController.php
index 134800b..da078ac 100644
--- a/core/modules/node/lib/Drupal/node/NodeTranslationController.php
+++ b/core/modules/node/lib/Drupal/node/NodeTranslationController.php
@@ -44,7 +44,7 @@ public function entityFormAlter(array &$form, array &$form_state, EntityInterfac
    * Overrides EntityTranslationController::entityFormTitle().
    */
   protected function entityFormTitle(EntityInterface $entity) {
-    $type_name = node_type_get_name($entity);
+    $type_name = node_get_type_label($entity);
     return t('<em>Edit @type</em> @title', array('@type' => $type_name, '@title' => $entity->label()));
   }
 }
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 7612487..82685dd 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityTranslationTest.php
@@ -365,7 +365,7 @@ function testEntityFormLanguage() {
 
     // Create a body translation and check the form language.
     $langcode2 = $this->langcodes[1];
-    $node->set('body', array(array('value' => $this->randomName(16))), $langcode2);
+    $node->body[$langcode2][0]['value'] = $this->randomName(16);
     $node->save();
     $this->drupalGet($langcode2 . '/node/' . $node->nid . '/edit');
     $form_langcode = variable_get('entity_form_langcode', FALSE);
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 602962f..57704d5 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -5,6 +5,9 @@
  * Test module for the entity API providing an entity type for testing.
  */
 
+use Drupal\entity_test\EntityTest;
+
+
 /**
  * Implements hook_entity_info().
  */
@@ -93,8 +96,8 @@ function entity_test_add() {
 /**
  * Menu callback: displays the 'Edit existing entity_test' form.
  */
-function entity_test_edit($entity) {
-  drupal_set_title(t('entity_test @id', array('@id' => $entity->id())), PASS_THROUGH);
+function entity_test_edit(EntityTest $entity) {
+  drupal_set_title($entity->label(), PASS_THROUGH);
   return entity_get_form($entity);
 }
 
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php
index 17e8470..1a19cf4 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php
@@ -55,4 +55,12 @@ public function __construct(array $values, $entity_type) {
     unset($this->name);
     unset($this->user_id);
   }
+
+  /**
+   * Overrides Drupal\entity\Entity::label().
+   */
+  public function label($langcode = LANGUAGE_DEFAULT) {
+    return $this->getTranslation($langcode)->name->value;
+  }
+
 }
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php
index e4a3eec..a65f06f 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php
@@ -54,21 +54,6 @@ public function form(array $form, array &$form_state, EntityInterface $entity) {
   }
 
   /**
-   * Overrides Drupal\Core\Entity\EntityFormController::submit().
-   */
-  public function submit(array $form, array &$form_state) {
-    $entity = parent::submit($form, $form_state);
-    $entity->setLangcode($form_state['values']['langcode']);
-    $langcode = $this->getFormLangcode($form_state);
-    // Updates multilingual properties.
-    $translation = $entity->getTranslation($langcode);
-    foreach (array('name', 'user_id') as $name) {
-      $translation->$name->setValue($form_state['values'][$name]);
-    }
-    return $entity;
-  }
-
-  /**
    * Overrides Drupal\Core\Entity\EntityFormController::save().
    */
   public function save(array $form, array &$form_state) {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
index 67e4b9b..41aa9dc 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php
@@ -85,6 +85,13 @@ protected function attachPropertyData(&$queried_entities) {
   protected function postSave(EntityInterface $entity, $update) {
     $default_langcode = $entity->language()->langcode;
 
+    // Delete and insert to handle removed values.
+    db_delete('entity_test_property_data')
+      ->condition('id', $entity->id())
+      ->execute();
+
+    $query = db_insert('entity_test_property_data');
+
     foreach ($entity->getTranslationLanguages() as $langcode => $language) {
       $translation = $entity->getTranslation($langcode);
 
@@ -96,12 +103,12 @@ protected function postSave(EntityInterface $entity, $update) {
         'user_id' => $translation->user_id->value,
       );
 
-      db_merge('entity_test_property_data')
-        ->fields($values)
-        ->condition('id', $values['id'])
-        ->condition('langcode', $values['langcode'])
-        ->execute();
+      $query
+        ->fields(array_keys($values))
+        ->values($values);
     }
+
+    $query->execute();
   }
 
   /**
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestTranslationController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestTranslationController.php
index 54d93e6..e7ca050 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestTranslationController.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestTranslationController.php
@@ -19,7 +19,10 @@ class EntityTestTranslationController extends EntityTranslationController {
    * Overrides EntityTranslationControllerInterface::removeTranslation().
    */
   public function removeTranslation(EntityInterface $entity, $langcode) {
-    $entity->setProperties(array(), $langcode);
-    return parent::removeTranslation($entity, $langcode);
+    $translation = $entity->getTranslation($langcode);
+    foreach ($translation->getPropertyDefinitions() as $property_name => $langcode) {
+      $translation->$property_name = array();
+    }
   }
+
 }
diff --git a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
index 9000503..ee9dc59 100644
--- a/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
+++ b/core/modules/translation_entity/lib/Drupal/translation_entity/Tests/EntityTranslationUITest.php
@@ -78,24 +78,26 @@ function testTranslationUI() {
     $field['translatable'] = TRUE;
     field_update_field($field);
 
-    // Create a new test entity with original values in the default language. 
+    // Create a new test entity with original values in the default language.
     $default_langcode = language_default()->langcode;
 
     $values[$default_langcode] = array(
       'langcode' => $default_langcode,
       'name' => $this->randomName(8),
-      'uid' => mt_rand(0, 128),
+      'user_id' => mt_rand(0, 128),
       'field_test_text' => $this->randomName(16),
     );
 
     $this->drupalPost('entity-test/add', $this->getEditValues($values, $default_langcode, TRUE), t('Save'));
-    $entity = current(entity_load_multiple_by_properties('entity_test', array('name' => $values[$default_langcode]['name'])));
+    $entity = $this->loadEntityByName($values[$default_langcode]['name']);
     $this->assertTrue($entity, t('Entity found in the database.'));
 
+    $translation = $entity->getTranslation($default_langcode);
     foreach ($values[$default_langcode] as $property => $value) {
       if ($property != 'langcode') {
-        $stored_value = $entity->get($property, $default_langcode);
-        $stored_value = is_array($stored_value) ? $stored_value[0]['value'] : $stored_value;
+        // @todo Remove this workaround when field default language is correctly
+        // handled.
+        $stored_value = $property != 'field_test_text' ? $translation->get($property)->value : $entity->values['field_test_text'][$default_langcode][0]['value'];
         $message = format_string('@property correctly stored in the default language.', array('@property' => $property));
         $this->assertEqual($stored_value, $value, $message);
       }
@@ -105,7 +107,7 @@ function testTranslationUI() {
     $langcode = 'it';
     $values[$langcode] = array(
       'name' => $this->randomName(8),
-      'uid' => mt_rand(0, 128),
+      'user_id' => mt_rand(0, 128),
       'field_test_text' => $this->randomName(16),
     );
 
@@ -116,20 +118,14 @@ function testTranslationUI() {
     // Switch the source language.
     $langcode = 'fr';
     $source_langcode = 'it';
-    $edit = array(
-      'source_langcode[source]' => $source_langcode,
-      // @todo Remove these once we support source values for properties. For
-      // now we need them as they are required to submit the form.
-      'name' => $this->randomName(8),
-      'uid' => mt_rand(0, 128),
-    );
+    $edit = array('source_langcode[source]' => $source_langcode);
     $this->drupalPost($langcode . '/entity-test/manage/' . $entity->id() . '/translations/add/' . $default_langcode, $edit, t('Change'));
     $this->assertFieldByXPath('//input[@name="field_test_text[fr][0][value]"]', $values[$source_langcode]['field_test_text'], 'Source language correctly switched.');
 
     // Add another translation and mark the other ones as outdated.
     $values[$langcode] = array(
       'name' => $this->randomName(8),
-      'uid' => mt_rand(0, 128),
+      'user_id' => mt_rand(0, 128),
       'field_test_text' => $this->randomName(16),
     );
     $edit = $this->getEditValues($values, $langcode) + array('translation[retranslate]' => TRUE);
@@ -138,10 +134,13 @@ function testTranslationUI() {
 
     // Check that the entered values have been correctly stored.
     foreach ($values as $langcode => $property_values) {
+      $translation = $entity->getTranslation($langcode);
       foreach ($property_values as $property => $value) {
         if ($property != 'langcode') {
-          $stored_value = $entity->get($property, $langcode);
-          $stored_value = is_array($stored_value) ? $stored_value[0]['value'] : $stored_value;
+          $stored_value = $translation->get($property);
+          // @todo Remove this workaround when field default language is correctly
+          // handled.
+          $stored_value = $property != 'field_test_text' ? $translation->get($property)->value : $entity->values['field_test_text'][$langcode][0]['value'];
           $message = format_string('%property correctly stored with language %language.', array('%property' => $property, '%language' => $langcode));
           $this->assertEqual($stored_value, $value, $message);
         }
@@ -169,12 +168,12 @@ function testTranslationUI() {
     $this->drupalPost(NULL, array(), t('Delete translation'));
     $this->drupalPost(NULL, array(), t('Delete'));
     $entity = entity_test_load($entity->id(), TRUE);
-    $translations = $entity->translations();
+    $translations = $entity->getTranslationLanguages();
     $this->assertTrue(count($translations) == 2 && empty($translations[$enabled_langcode]), 'Translation successfully deleted.');
   }
 
   /**
-   * Loads a test entity by name always resetting the storage controller cache.
+   * Returns an edit array containing the values to be posted.
    */
   protected function getEditValues($values, $langcode, $new = FALSE) {
     $edit = $values[$langcode];
@@ -183,4 +182,14 @@ protected function getEditValues($values, $langcode, $new = FALSE) {
     unset($edit['field_test_text']);
     return $edit;
   }
+
+  /**
+   * Loads a test entity by name.
+   *
+   * @return Drupal\entity_test\EntityTest
+   *   A test entity matching the given name.
+   */
+  protected function loadEntityByName($name) {
+    return current(entity_load_multiple_by_properties('entity_test', array('name' => $name)));
+  }
 }
diff --git a/core/modules/translation_entity/translation_entity.pages.inc b/core/modules/translation_entity/translation_entity.pages.inc
index 782af7d..eb6a1a5 100644
--- a/core/modules/translation_entity/translation_entity.pages.inc
+++ b/core/modules/translation_entity/translation_entity.pages.inc
@@ -7,6 +7,7 @@
 
 use Drupal\Core\Language\Language;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityNG;
 use Drupal\translation_entity\EntityTranslationController;
 
 /**
@@ -63,8 +64,8 @@ function translation_entity_overview(EntityInterface $entity) {
 
         // @todo Consider supporting the ability to track translation publishing
         // status independently from entity status, as it may not exist.
-        $translation_status = $entity->get('status', $langcode);
-        $status = !isset($translation_status) || $translation_status ? t('Published') : t('Not published');
+        $translation = $entity->getTranslation($langcode, FALSE);
+        $status = !isset($translation->status) || $translation->status ? t('Published') : t('Not published');
         // @todo Add a theming function here.
         $status .= !empty($entity->retranslate[$langcode]) ? ' - <span class="marker">' . t('outdated') . '</span>' : '';
 
@@ -137,6 +138,7 @@ function _translation_entity_get_switch_links($path) {
 function translation_entity_add_page(EntityInterface $entity, Language $source = NULL, Language $target = NULL) {
   $source = !empty($source) ? $source : $entity->language();
   $target = !empty($target) ? $target : language(LANGUAGE_TYPE_CONTENT);
+  // @todo Exploit the upcoming hook_entity_prepare() when available.
   translation_entity_prepare_translation($entity, $source, $target);
   $info = $entity->entityInfo();
   $operation = isset($info['default operation']) ? $info['default operation'] : 'default';
@@ -151,12 +153,35 @@ function translation_entity_add_page(EntityInterface $entity, Language $source =
  * Populates target values with the source values.
  */
 function translation_entity_prepare_translation(EntityInterface $entity, Language $source, Language $target) {
-  // @todo Exploit the upcoming hook_entity_prepare() when available.
-  foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $field_name => $instance) {
-    $field = field_info_field($field_name);
-    if (!empty($field['translatable'])) {
-      $items = $entity->get($field_name, $source->langcode);
-      $entity->set($field_name, $items, $target->langcode);
+  // @todo Unify field and propesrty handling.
+  $instances = field_info_instances($entity->entityType(), $entity->bundle());
+
+  if ($entity instanceof EntityNG) {
+    $source_translation = $entity->getTranslation($source->langcode);
+    $target_translation = $entity->getTranslation($target->langcode);
+
+    foreach ($target_translation->getPropertyDefinitions() as $property_name => $definition) {
+      if (!isset($instances[$property_name])) {
+        // @todo Actually retrieving the property value should not be necessary.
+        $target_translation->$property_name = $source_translation->$property_name->value;
+      }
+      else {
+        $entity->setCompatibilityMode(TRUE);
+        $value = $entity->$property_name;
+        $value[$target->langcode] = $value[$source->langcode];
+        $entity->$property_name = $value;
+        $entity->setCompatibilityMode(FALSE);
+      }
+    }
+  }
+  else {
+    foreach ($instances as $field_name => $instance) {
+      $field = field_info_field($field_name);
+      if (!empty($field['translatable'])) {
+        $value = $entity->get($field_name);
+        $value[$target->langcode] = $value[$source->langcode];
+        $entity->set($field_name, $value);
+      }
     }
   }
 }
