diff --git a/includes/commerce_line_item.inline_entity_form.inc b/includes/commerce_line_item.inline_entity_form.inc
index 642affb..0c767b9 100644
--- a/includes/commerce_line_item.inline_entity_form.inc
+++ b/includes/commerce_line_item.inline_entity_form.inc
@@ -98,7 +98,7 @@ class CommerceLineItemInlineEntityFormController extends EntityInlineEntityFormC
       '#weight' => $extra_fields['label']['weight'],
       '#fieldset' => 'line_item_details',
     );
-    field_attach_form('commerce_line_item', $line_item, $entity_form, $form_state);
+    $entity_form = parent::entityForm($entity_form, $form_state);
 
     // Tweaks specific to product line items.
     if (in_array($line_item->type, $this->productLineItemTypes())) {
diff --git a/includes/commerce_product.inline_entity_form.inc b/includes/commerce_product.inline_entity_form.inc
index 5dcb6f2..9b95433 100644
--- a/includes/commerce_product.inline_entity_form.inc
+++ b/includes/commerce_product.inline_entity_form.inc
@@ -194,9 +194,7 @@ class CommerceProductInlineEntityFormController extends EntityInlineEntityFormCo
       '#weight' => $extra_fields['status']['weight'],
     );
 
-    // Attach fields.
-    $langcode = entity_language('commerce_product', $product);
-    field_attach_form('commerce_product', $product, $entity_form, $form_state, $langcode);
+    $entity_form = parent::entityForm($entity_form, $form_state);
 
     // Hide or disable the SKU field if it is auto-generated by Commerce AutoSKU.
     if (module_exists('commerce_autosku') && $settings = commerce_autosku_get_settings($product)) {
@@ -359,7 +357,10 @@ class CommerceProductInlineEntityFormController extends EntityInlineEntityFormCo
 
     // Generate the product title. Take the parent entity title as the base.
     if ($this->settings['autogenerate_title']) {
-      $entity->title = entity_label($context['parent_entity_type'], $context['parent_entity']);
+      // Update the entity label only with a valid value.
+      if ($label = entity_label($context['parent_entity_type'], $context['parent_entity'])) {
+        $entity->title = $label;
+      }
       $attributes = $this->attributes($entity->type);
       if (!empty($attributes)) {
         $wrapper = entity_metadata_wrapper('commerce_product', $entity);
@@ -375,6 +376,18 @@ class CommerceProductInlineEntityFormController extends EntityInlineEntityFormCo
           $entity->title .= ' (' . implode(', ', $attribute_values) . ')';
         }
       }
+
+      // Update the autogenerated title field, otherwise when dealing with
+      // translations the source language would be used.
+      if (module_exists('title') && entity_label($this->entityType, $entity)) {
+        $legacy_field = 'title';
+        list(, , $bundle) = entity_extract_ids($this->entityType, $entity);
+        if (title_field_replacement_enabled($this->entityType, $bundle, $legacy_field)) {
+          $info = title_field_replacement_info($this->entityType, $legacy_field);
+          $langcode = $info['field']['translatable'] ? entity_language($this->entityType, $entity) : LANGUAGE_NONE;
+          title_field_sync_set($this->entityType, $entity, $legacy_field, $info, $langcode);
+        }
+      }
     }
 
     entity_save('commerce_product', $entity);
diff --git a/includes/entity.inline_entity_form.inc b/includes/entity.inline_entity_form.inc
index 89a4246..6536630 100644
--- a/includes/entity.inline_entity_form.inc
+++ b/includes/entity.inline_entity_form.inc
@@ -272,10 +272,85 @@ class EntityInlineEntityFormController {
       field_attach_form($this->entityType, $entity, $entity_form, $form_state, $langcode);
     }
 
+    $this->entityFormTranslation($entity_form);
     return $entity_form;
   }
 
   /**
+   * Handles entity translation for inline entities.
+   *
+   * @param $entity_form
+   *   The entity form.
+   */
+  protected function entityFormTranslation(&$entity_form) {
+    if (($handler = module_invoke('entity_translation', 'get_handler', $this->entityType, $entity_form['#entity'])) && !$handler->isNewEntity()) {
+      $form_langcode = $handler->getActiveLanguage();
+      $langcode = !empty($entity_form['#parent_language']) ? $entity_form['#parent_language'] : $handler->getLanguage();
+      $translations = $handler->getTranslations();
+      $update_langcode = $form_langcode && ($form_langcode != $langcode);
+      $source = $handler->getSourceLanguage();
+      $new_translation = !isset($translations->data[$form_langcode]);
+
+      if (!isset($translations->data[$form_langcode]) || count($translations->data) > 1) {
+        $handler->entityFormSharedElements($entity_form);
+      }
+
+      // If we are creating a new translation we need to retrieve form elements
+      // populated with the source language values. In this case source values
+      // have already been populated, so we need to preserve possible changes.
+      // There might be situations, e.g. ajax calls, where the form language
+      // has not been properly initialized before calling field_attach_form().
+      // In this case we need to rebuild the form with the correct form language
+      // and replace the field elements with the correct ones.
+      // Borrowed some code from entity_translation_field_attach_form()
+      // that won't get run because $form_state['rebuild'] is TRUE for all IEF
+      // forms.
+      if ($update_langcode || ($source && !isset($translations->data[$form_langcode]) && isset($translations->data[$source]))) {
+        $entity_type = $entity_form['#entity_type'];
+        list($id, , $bundle) = entity_extract_ids($entity_type, $entity_form['#entity']);
+        foreach (field_info_instances($entity_type, $bundle) as $instance) {
+
+          $field_name = $instance['field_name'];
+          $field = field_info_field($field_name);
+
+          // If we are creating a new translation we have to change the form
+          // item language information from source to target language, this way
+          // the user can find the form items already populated with the source
+          // values while the field form element holds the correct language
+          // information.
+          if ($field['translatable']) {
+            $element = &$entity_form[$field_name];
+            $element['#entity_type'] = $entity_type;
+            $element['#entity'] = $entity_form['#entity'];
+            $element['#entity_id'] = $id;
+            $element['#field_name'] = $field_name;
+            $element['#source'] = $update_langcode ? $form_langcode : $source;
+            $element['#previous'] = NULL;
+            $element['#form_parents'] = $entity_form['#parents'];
+
+            // If we are updating the form language we need to make sure that
+            // the wrong language is unset and the right one is stored in the
+            // field element (see entity_translation_prepare_element()).
+            if ($update_langcode) {
+              $element['#previous'] = $element['#language'];
+              $element['#language'] = $form_langcode;
+            }
+
+            // Swap default values during form processing to avoid recursion.
+            // We try to act before any other callback so that the correct
+            // values are already in place for them.
+            if (!isset($element['#process'])) {
+              $element['#process'] = array();
+            }
+            array_unshift($element['#process'], 'entity_translation_prepare_element');
+          }
+        }
+      }
+      $entity_form['#element_validate'][] = 'entity_translation_entity_form_validate';
+    }
+  }
+
+  /**
    * Validates the entity form.
    *
    * @param $entity_form
@@ -308,7 +383,7 @@ class EntityInlineEntityFormController {
     $info = entity_get_info($this->entityType);
     list(, , $bundle) = entity_extract_ids($this->entityType, $entity_form['#entity']);
     $entity = $entity_form['#entity'];
-    $entity_values = drupal_array_get_nested_value($form_state['values'], $entity_form['#parents']);
+    $entity_values = &drupal_array_get_nested_value($form_state['values'], $entity_form['#parents']);
 
     // Copy top-level form values that are not for fields to entity properties,
     // without changing existing entity properties that are not being edited by
@@ -318,8 +393,61 @@ class EntityInlineEntityFormController {
       $entity->$key = $value;
     }
 
+    // Update the entity language using the parent entity submitted value.
+    if (!empty($info['entity keys']['language'])) {
+      $parent_info = entity_get_info($entity_form['#parent_entity_type']);
+      if (isset($parent_info['entity keys']['language']) && isset($form_state['values'][$parent_info['entity keys']['language']])) {
+        $entity->{$info['entity keys']['language']} = $form_state['values'][$parent_info['entity keys']['language']];
+        $handler = module_invoke('entity_translation', 'get_handler', $this->entityType, $entity);
+        $lang = $handler->getActiveLanguage();
+        if ($lang == LANGUAGE_NONE) {
+          if ($entity_form['#parent_language'] != LANGUAGE_NONE) {
+            $handler->setFormLanguage($entity_form['#parent_language']);
+          }
+          else {
+            $handler->setFormLanguage($form_state['values'][$parent_info['entity keys']['language']]);
+          }
+        }
+      }
+    }
+
     if ($info['fieldable']) {
+      // Retrieve the current entity form language.
+      $langcode = entity_language($this->entityType, $entity);
+
+      // Handle a possible language change: new language values are inserted,
+      // previous ones are deleted.
+      foreach (field_info_instances($this->entityType, $bundle) as $instance) {
+        $field_name = $instance['field_name'];
+        $field = field_info_field($field_name);
+        $previous_langcode = $entity_form[$field_name]['#language'];
+        if ($field['translatable'] && $previous_langcode != $langcode && ($langcode != LANGUAGE_NONE && $previous_langcode != language_default('language'))) {
+          $entity_values[$field_name][$langcode] = $entity_values[$field_name][$previous_langcode];
+          $entity_values[$field_name][$previous_langcode] = array();
+        }
+      }
+
       field_attach_submit($this->entityType, $entity, $entity_form, $form_state);
+
+      // Handle translation submission.
+      $this->entityTranslationFormSubmit($entity_form, $entity);
+    }
+  }
+
+  /**
+   * Creates an entity translation if needed.
+   */
+  protected function entityTranslationFormSubmit($entity_form, $entity) {
+    if (($handler = module_invoke('entity_translation', 'get_handler', $this->entityType, $entity)) && ($source = $handler->getSourceLanguage())) {
+      list($id, , ) = entity_extract_ids($this->entityType, $entity);
+      $translation = array(
+        'entity_type' => $this->entityType,
+        'entity_id' => $id,
+        'language' => $handler->getActiveLanguage(),
+        'source' => $source,
+        'status' => 1,
+      );
+      $handler->setTranslation($translation);
     }
   }
 
@@ -362,7 +490,7 @@ class EntityInlineEntityFormController {
    * @param $form_state
    *   The form state of the parent form.
    *
-   * @return
+   * @return int
    *   IEF_ENTITY_UNLINK or IEF_ENTITY_UNLINK_DELETE.
    */
   public function removeFormSubmit($remove_form, &$form_state) {
@@ -383,6 +511,31 @@ class EntityInlineEntityFormController {
   }
 
   /**
+   * Returns the remove translation form to be shown through the IEF widget.
+   *
+   * @param $remove_form
+   *   The remove form.
+   * @param $form_state
+   *   The form state of the parent form.
+   */
+  public function removeTranslationForm($remove_form, &$form_state) {
+    $entity = $remove_form['#entity'];
+    list($entity_id) = entity_extract_ids($this->entityType, $entity);
+    $entity_label = entity_label($this->entityType, $entity);
+    $langcode = entity_language($this->entityType, $entity);
+    $languages = language_list();
+
+    $remove_form['message'] = array(
+      '#markup' => '<div>' . t('Are you sure you want to remove the @language_label translation for %label?', array(
+          '%label' => $entity_label,
+          '@language_label' => isset($languages[$langcode]) ? $languages[$langcode]->name : $langcode,
+        )) . '</div>',
+    );
+
+    return $remove_form;
+  }
+
+  /**
    * Creates a clone of the given entity.
    *
    * Copies the entity_ui_clone_entity() approach, extending it to unset
diff --git a/includes/node.inline_entity_form.inc b/includes/node.inline_entity_form.inc
index 4d481cb..c879b5c 100644
--- a/includes/node.inline_entity_form.inc
+++ b/includes/node.inline_entity_form.inc
@@ -65,10 +65,7 @@ class NodeInlineEntityFormController extends EntityInlineEntityFormController {
       '#weight' => 99,
     );
 
-    $langcode = entity_language('node', $node);
-    field_attach_form('node', $node, $entity_form, $form_state, $langcode);
-
-    return $entity_form;
+    return parent::entityForm($entity_form, $form_state);
   }
 
   /**
diff --git a/includes/taxonomy_term.inline_entity_form.inc b/includes/taxonomy_term.inline_entity_form.inc
index bd2ec59..eb1667c 100644
--- a/includes/taxonomy_term.inline_entity_form.inc
+++ b/includes/taxonomy_term.inline_entity_form.inc
@@ -85,10 +85,7 @@ class TaxonomyTermInlineEntityFormController extends EntityInlineEntityFormContr
       '#weight' => !empty($extra_fields['description']) ? $extra_fields['description']['weight'] : -4,
     );
 
-    $langcode = entity_language('taxonomy_term', $term);
-    field_attach_form('taxonomy_term', $term, $entity_form, $form_state, $langcode);
-
-    return $entity_form;
+    return parent::entityForm($entity_form, $form_state);
   }
 
 
diff --git a/inline_entity_form.info b/inline_entity_form.info
index a5a87db..bc6a4c3 100644
--- a/inline_entity_form.info
+++ b/inline_entity_form.info
@@ -14,3 +14,4 @@ files[] = includes/commerce_product.inline_entity_form.inc
 files[] = includes/commerce_line_item.inline_entity_form.inc
 files[] = tests/inline_entity_form_test_base.test
 files[] = tests/multiple_values_widget.test
+files[] = tests/entity_translation_integration.test
diff --git a/inline_entity_form.module b/inline_entity_form.module
index c1a7d82..267baa5 100644
--- a/inline_entity_form.module
+++ b/inline_entity_form.module
@@ -191,6 +191,46 @@ function inline_entity_form_entity_delete($entity, $type) {
 }
 
 /**
+ * Implements hook_entity_translation_delete().
+ *
+ * Deletes a translation of the referenced entity.
+ */
+function inline_entity_form_entity_translation_delete($entity_type, $entity, $langcode) {
+  list(,, $bundle) = entity_extract_ids($entity_type, $entity);
+  foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) {
+    if (strpos($instance['widget']['type'], 'inline_entity_form') === 0) {
+      $controller = inline_entity_form_get_controller($instance);
+
+      // The controller specified that referenced entities should be deleted.
+      if ($controller && $controller->getSetting('delete_references')) {
+        $items = field_get_items($entity_type, $entity, $field_name, $langcode);
+        if ($items) {
+          $field = field_info_field($field_name);
+          $ief_settings = inline_entity_form_settings($field, $instance);
+
+          $ids = array();
+          foreach ($items as $item) {
+            $ids[] = $item[$ief_settings['column']];
+          }
+
+          $ref_entity_type = $ief_settings['entity_type'];
+          $context = array(
+            'parent_entity_type' => $entity_type,
+            'parent_entity' => $entity,
+          );
+
+          foreach (entity_load($ref_entity_type, $ids) as $id => $ref_entity) {
+            $handler = entity_translation_get_handler($ref_entity_type, $ref_entity);
+            $handler->removeTranslation($langcode);
+            $controller->save($ref_entity, $context);
+          }
+        }
+      }
+    }
+  }
+}
+
+/**
  * Attaches theme specific CSS files.
  *
  * @param $theme_css
@@ -397,6 +437,7 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
   $widget = $instance['widget'];
   $settings = inline_entity_form_settings($field, $instance);
   $entity_info = entity_get_info($settings['entity_type']);
+  $parent_entity_info = entity_get_info($element['#entity_type']);
   $controller = inline_entity_form_get_controller($instance);
   // The current entity type is not supported, execution can't continue.
   if (!$controller) {
@@ -406,11 +447,27 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
   // Get the entity type labels for the UI strings.
   $labels = $controller->labels();
 
+  // Use current form language for translatable field.
+  if (!empty($form_state['entity_translation']['is_translation']) && $langcode != LANGUAGE_NONE) {
+    $langcode = $form_state['entity_translation']['form_langcode'];
+  }
+
   // Build a parents array for this element's values in the form.
-  $parents = array_merge($element['#field_parents'], array($element['#field_name'], $element['#language']));
+  $parents = array_merge($element['#field_parents'], array($element['#field_name'], $langcode));
 
-  // Get the langcode of the parent entity.
-  $parent_langcode = entity_language($element['#entity_type'], $element['#entity']);
+  // If the parent entity is new, the language is not yet set. Use the langcode
+  // from the parent form if existing in this case.
+  if (!isset($element['#entity']->{$parent_entity_info['entity keys']['id']}) && isset($form_state['complete form']['language'])) {
+    $parent_langcode = isset($form_state['complete form']['language']['#value']) ? $form_state['complete form']['language']['#value'] : $form_state['complete form']['language']['#default_value'];
+    $parent_is_translation = FALSE;
+  }
+  else {
+    // Get the langcode of the parent entity.
+    $parent_langcode = entity_language($element['#entity_type'], $element['#entity']);
+    $handler = entity_translation_get_handler($element['#entity_type'], $element['#entity']);
+    $translations = $handler->getTranslations();
+    $parent_is_translation = isset($translations->original) && $parent_langcode != $translations->original;
+  }
 
   // Assign a unique identifier to each IEF widget.
   // Since $parents can get quite long, sha1() ensures that every id has
@@ -508,6 +565,8 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
       '#parents' => array_merge($parents, array('form')),
       // Pass the current entity type.
       '#entity_type' => $settings['entity_type'],
+      '#parent_entity' => $element['#entity'],
+      '#parent_entity_type' => $element['#entity_type'],
       // Pass the langcode of the parent entity,
       '#parent_language' => $parent_langcode,
       // Identifies the IEF widget to which the form belongs.
@@ -577,6 +636,8 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
           '#entity' => $entity,
           '#entity_type' => $settings['entity_type'],
           // Pass the langcode of the parent entity,
+          '#parent_entity' => $element['#entity'],
+          '#parent_entity_type' => $element['#entity_type'],
           '#parent_language' => $parent_langcode,
           // Identifies the IEF widget to which the form belongs.
           '#ief_id' => $ief_id,
@@ -608,12 +669,18 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
           '#attributes' => array('class' => array('ief-entity-operations')),
         );
 
+        // If we are editing a translation and the inline entity is
+        // translated, provide some different options.
+        $handler = entity_translation_get_handler($controller->entityType(), $entity);
+        $translations = $handler->getTranslations();
+        $is_translation = $parent_is_translation && isset($translations->original) && $parent_langcode != $translations->original && isset($translations->data[$parent_langcode]);
+
         // Make sure entity_access is not checked for unsaved entities.
         list($entity_id) = entity_extract_ids($controller->entityType(), $entity);
         if (empty($entity_id) || entity_access('update', $controller->entityType(), $entity)) {
           $row['actions']['ief_entity_edit'] = array(
             '#type' => 'submit',
-            '#value' => t('Edit'),
+            '#value' => $is_translation ? t('Edit translation') : ($parent_is_translation ? t('Add translation') : t('Edit')),
             '#name' => 'ief-' . $ief_id . '-entity-edit-' . $key,
             '#limit_validation_errors' => array(),
             '#ajax' => array(
@@ -629,7 +696,7 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
         // The clone form follows the same semantics as the create form, so
         // it's opened below the table.
         if ($controller->getSetting('allow_clone') && !$cardinality_reached
-          && entity_access('create', $controller->entityType(), $entity)) {
+          && entity_access('create', $controller->entityType(), $entity) && !$parent_is_translation) {
           $row['actions']['ief_entity_clone'] = array(
             '#type' => 'submit',
             '#value' => t('Clone'),
@@ -650,19 +717,41 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
         // removeForm() method.
         if (empty($entity_id) || $controller->getSetting('allow_existing')
           || entity_access('delete', $controller->entityType(), $entity)) {
-          $row['actions']['ief_entity_remove'] = array(
-            '#type' => 'submit',
-            '#value' => t('Remove'),
-            '#name' => 'ief-' . $ief_id . '-entity-remove-' . $key,
-            '#limit_validation_errors' => array(),
-            '#ajax' => array(
-              'callback' => 'inline_entity_form_get_element',
-              'wrapper' => $wrapper,
-            ),
-            '#submit' => array('inline_entity_form_open_row_form'),
-            '#ief_row_delta' => $key,
-            '#ief_row_form' => 'remove',
-          );
+
+          // Either provide a button to remove the translation or to remove
+          // the whole reference.
+          if ($is_translation) {
+            $row['actions']['ief_entity_remove_translation'] = array(
+              '#type' => 'submit',
+              '#value' => t('Remove translation'),
+              '#name' => 'ief-' . $ief_id . '-entity-remove-' . $key,
+              '#limit_validation_errors' => array(),
+              '#ajax' => array(
+                'callback' => 'inline_entity_form_get_element',
+                'wrapper' => $wrapper,
+              ),
+              '#submit' => array('inline_entity_form_open_row_form'),
+              '#ief_row_delta' => $key,
+              '#ief_row_form' => 'remove',
+              '#ief_row_is_translation' => $is_translation,
+            );
+          }
+          elseif (!$parent_is_translation) {
+            $row['actions']['ief_entity_remove'] = array(
+              '#type' => 'submit',
+              '#value' => t('Remove'),
+              '#name' => 'ief-' . $ief_id . '-entity-remove-' . $key,
+              '#limit_validation_errors' => array(),
+              '#ajax' => array(
+                'callback' => 'inline_entity_form_get_element',
+                'wrapper' => $wrapper,
+              ),
+              '#submit' => array('inline_entity_form_open_row_form'),
+              '#ief_row_delta' => $key,
+              '#ief_row_form' => 'remove',
+              '#ief_row_is_translation' => $is_translation,
+            );
+          }
         }
       }
     }
@@ -714,7 +803,7 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
       );
 
       // The user is allowed to create an entity of at least one bundle.
-      if (count($settings['create_bundles'])) {
+      if (count($settings['create_bundles']) && !$parent_is_translation) {
         // Let the user select the bundle, if multiple are available.
         if (count($settings['create_bundles']) > 1) {
           $bundles = array();
@@ -778,6 +867,8 @@ function inline_entity_form_field_widget_form(&$form, &$form_state, $field, $ins
         // values in $form_state.
         '#parents' => array_merge($parents, array('form')),
         // Pass the current entity type.
+        '#parent_entity' => $element['#entity'],
+        '#parent_entity_type' => $element['#entity_type'],
         '#entity_type' => $settings['entity_type'],
         // Pass the langcode of the parent entity,
         '#parent_language' => $parent_langcode,
@@ -904,6 +995,16 @@ function inline_entity_form_entity_form($controller, $entity_form, &$form_state)
     $save_label = t('Clone @type_singular', array('@type_singular' => $labels['singular']));
   }
 
+  // Register a child entity translation handler to properly deal with the
+  // entity form language.
+  list(, , $bundle) = entity_extract_ids($entity_form['#entity_type'], $entity_form['#entity']);
+  if (module_invoke('entity_translation', 'enabled', $entity_form['#entity_type'], $bundle) && $entity_form['#parent_entity']->translations->original != null) {
+    inline_entity_form_add_child_translation_handler($entity_form);
+    // Ensure this is executed even with cached forms. This is mainly useful
+    // when dealing with AJAX calls.
+    $entity_form['#process'][] = 'inline_entity_form_add_child_translation_handler';
+  }
+
   // Retrieve the form provided by the controller.
   $entity_form = $controller->entityForm($entity_form, $form_state);
 
@@ -977,6 +1078,22 @@ function inline_entity_form_entity_form($controller, $entity_form, &$form_state)
 }
 
 /**
+ * Registers a child entity translation handler for the given element.
+ */
+function inline_entity_form_add_child_translation_handler($element) {
+  $handler = entity_translation_get_handler($element['#parent_entity_type'], $element['#parent_entity']);
+
+  $handler->setFormLanguage($element['#parent_language']);
+  $source = $handler->getSourceLanguage();
+  if (!($source) && $element['#parent_entity']->translations->original != $element['#parent_language']) {
+    $handler->setSourceLanguage($element['#parent_entity']->translations->original);
+  }
+
+  $handler->addChild($element['#entity_type'], $element['#entity']);
+  return $element;
+}
+
+/**
  * Validates an entity form.
  *
  * @param $entity_form
@@ -1211,12 +1328,21 @@ function inline_entity_form_remove_form($controller, $remove_form, &$form_state)
   $delta = $remove_form['#ief_id'] . '-' . $remove_form['#ief_row_delta'];
 
   // Retrieve the form provided by the controller.
-  $remove_form = $controller->removeForm($remove_form, $form_state);
+  $row_is_translation = $form_state['triggering_element']['#ief_row_is_translation'];
+  if ($row_is_translation) {
+    $remove_form = $controller->removeTranslationForm($remove_form, $form_state);
+  }
+  else {
+    $remove_form = $controller->removeForm($remove_form, $form_state);
+  }
   // Add the actions
   $remove_form['actions'] = array(
     '#type' => 'container',
     '#weight' => 100,
   );
+  // @todo: Compare entity orignal language with translation langauge. IF this
+  // is a translation, switch buttons and replace inline_entity_form_remove_confirm
+  // with variant that calls removeTranslationFormSubmit on the handler.
   $remove_form['actions']['ief_remove_confirm'] = array(
     '#type' => 'submit',
     '#value' => t('Remove'),
@@ -1226,7 +1352,7 @@ function inline_entity_form_remove_form($controller, $remove_form, &$form_state)
       'callback' => 'inline_entity_form_get_element',
       'wrapper' => 'inline-entity-form-' . $remove_form['#ief_id'],
     ),
-    '#submit' => array('inline_entity_form_remove_confirm'),
+    '#submit' => array($row_is_translation ? 'inline_entity_form_remove_translation_confirm' : 'inline_entity_form_remove_confirm'),
     '#ief_row_delta' => $remove_form['#ief_row_delta'],
   );
   $remove_form['actions']['ief_remove_cancel'] = array(
@@ -1281,6 +1407,36 @@ function inline_entity_form_remove_confirm($form, &$form_state) {
 }
 
 /**
+ * Remove translation form submit callback.
+ *
+ * The row is identified by #ief_row_delta stored on the triggering
+ * element.
+ * This isn't an #element_validate callback to avoid processing the
+ * remove form when the main form is submitted.
+ *
+ * @param $form
+ *   The complete parent form.
+ * @param $form_state
+ *   The form state of the parent form.
+ */
+function inline_entity_form_remove_translation_confirm($form, &$form_state) {
+  $form_state['rebuild'] = TRUE;
+  $element = inline_entity_form_get_element($form, $form_state);
+  $ief_id = $element['#ief_id'];
+  $delta = $form_state['triggering_element']['#ief_row_delta'];
+  $remove_form = $element['entities'][$delta]['form'];
+  $entity = $form_state['inline_entity_form'][$ief_id]['entities'][$delta]['entity'];
+
+  $settings = $form_state['inline_entity_form'][$ief_id]['settings'];
+  $handler = entity_translation_get_handler($settings['entity_type'], $entity);
+  $handler->removeTranslation($remove_form['#parent_language']);
+  $form_state['inline_entity_form'][$ief_id]['entities'][$delta]['needs_save'] = TRUE;
+
+  // Close form.
+  $form_state['inline_entity_form'][$ief_id]['entities'][$delta]['form'] = NULL;
+}
+
+/**
  * Button #submit callback: Triggers submission of entity forms.
  *
  * @param $form
@@ -1550,6 +1706,20 @@ function inline_entity_form_field_attach_submit($parent_entity_type, $parent_ent
       $need_reset = FALSE;
       foreach ($values['entities'] as $item) {
         if ($item['needs_save']) {
+
+          // Ensure the proper entity form language is set before saving.
+          if (module_invoke('entity_translation', 'enabled', $entity_type, $item['entity']) && ($handler = module_invoke('entity_translation', 'get_handler', $entity_type, $item['entity']))) {
+            // Fetch the parent language - with entity_translation this will
+            // return the current form language and thus match perfectly.
+            $parent_entity_language = entity_language($parent_entity_type, $parent_entity);
+            $entity_form_language = $handler->getActiveLanguage();
+            // If the field is language independent set the parent entity
+            // language as form language of the entity.
+            if ($langcode == LANGUAGE_NONE && $entity_form_language != $parent_entity_language) {
+              $handler->setFormLanguage($parent_entity_language);
+            }
+          }
+
           $controller->save($item['entity'], $context);
           $need_reset = TRUE;
         }
diff --git a/tests/entity_translation_integration.test b/tests/entity_translation_integration.test
new file mode 100644
index 0000000..8e440bf
--- /dev/null
+++ b/tests/entity_translation_integration.test
@@ -0,0 +1,256 @@
+<?php
+
+/**
+ * IEF-EntityTranslation integration tests.
+ *
+ * @group inline_entity_form
+ */
+class EntityTranslationIntegrationTest extends InlineEntityFormTestBase {
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Entity translation integration',
+      'description' => 'Tests the integration of Entity Translation with the Inline Entity Form.',
+      'group' => 'Inline entity form',
+    );
+  }
+
+  /**
+   * @see InlineEntityFormTestBase::setUp()
+   */
+  protected function setUp() {
+    $modules = array(
+      'inline_entity_form',
+      'inline_entity_form_test',
+      'locale',
+      'entity_translation',
+      'entityreference',
+    );
+    parent::setUp($modules);
+
+    $this->administrator_user = $this->drupalCreateUser(array(
+      'create ief_reference_type content',
+      'edit any ief_reference_type content',
+      'delete any ief_reference_type content',
+      'create ief_test_multiple content',
+      'edit any ief_test_multiple content',
+      'delete any ief_test_multiple content',
+      'bypass node access',
+      'administer nodes',
+      'administer fields',
+      'administer languages',
+      'administer content types',
+      'administer blocks',
+      'access administration pages',
+      'administer site configuration',
+      'administer entity translation',
+      'translate any entity',
+    ));
+    $this->drupalLogin($this->administrator_user);
+    $this->addLanguage('de');
+    $this->enableUrlLanguageDetection();
+    $this->configureContentTypes();
+
+    $this->formContentAddUrl = 'node/add/ief-test-multiple';
+  }
+
+  /**
+   * Enable URL language detection.
+   */
+  protected function enableUrlLanguageDetection() {
+    // Enable URL language detection and selection.
+    $edit = array(
+      'language[enabled][locale-url]' => TRUE,
+      'language_content[enabled][locale-interface]' => TRUE,
+    );
+    $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
+    $this->assertRaw(t('Language negotiation configuration saved.'), t('URL language detection enabled.'));
+    $this->drupalGet('admin/config/regional/language/configure');
+    // Reset caches.
+    drupal_static_reset('locale_url_outbound_alter');
+    drupal_static_reset('language_list');
+  }
+
+  /**
+   * Install a specified language if it has not been already.
+   *
+   * Otherwise make sure that the language is enabled.
+   *
+   * @param $langcode
+   *   The language code to check.
+   */
+  protected function addLanguage($langcode) {
+    // Check to make sure that language has not already been installed.
+    $this->drupalGet('admin/config/regional/language');
+
+    if (strpos($this->drupalGetContent(), 'enabled[' . $langcode . ']') === FALSE) {
+      // Doesn't have language installed so add it.
+      $edit = array();
+      $edit['langcode'] = $langcode;
+      $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
+
+      // Make sure we are not using a stale list.
+      drupal_static_reset('language_list');
+      $languages = language_list('language');
+      $this->assertTrue(array_key_exists($langcode, $languages), t('Language was installed successfully.'));
+
+      if (array_key_exists($langcode, $languages)) {
+        $this->assertRaw(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array('%language' => $languages[$langcode]->name, '@locale-help' => url('admin/help/locale'))), t('Language has been created.'));
+      }
+    }
+    elseif ($this->xpath('//input[@type="checkbox" and @name=:name and @checked="checked"]', array(':name' => 'enabled[' . $langcode . ']'))) {
+      // It is installed and enabled. No need to do anything.
+      $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed and enabled.');
+    }
+    else {
+      // It is installed but not enabled. Enable it.
+      $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed.');
+      $this->drupalPost(NULL, array('enabled[' . $langcode . ']' => TRUE), t('Save configuration'));
+      $this->assertRaw(t('Configuration saved.'), t('Language successfully enabled.'));
+    }
+  }
+
+  /**
+   * Configure the "Inline entity form test" provided content types.
+   */
+  protected function configureContentTypes() {
+
+    // Configure Entity translation for each content type.
+    variable_set('entity_translation_settings_node__ief_reference_type', array(
+      'default_language' => 'xx-et-current',
+      'hide_language_selector' => 0,
+      'exclude_language_none' => 0,
+      'lock_language' => 0,
+      'shared_fields_original_only' => 0,
+    ));
+    variable_set('entity_translation_settings_node__ief_test_multiple', array(
+      'default_language' => 'xx-et-current',
+      'hide_language_selector' => 0,
+      'exclude_language_none' => 0,
+      'lock_language' => 0,
+      'shared_fields_original_only' => 0,
+    ));
+
+    // Make the ief_reference_type and the ief_test_multiple multilingual.
+    foreach (array('ief_reference_type' => 'IEF reference type', 'ief_test_multiple' => 'IEF test multiple') as $ief_content_type_machine_name => $ief_content_type) {
+      $edit = array();
+      $edit['language_content_type'] = ENTITY_TRANSLATION_ENABLED;
+      $this->drupalGet('admin/structure/types/manage/' . $ief_content_type_machine_name);
+      $this->drupalPost('admin/structure/types/manage/' . $ief_content_type_machine_name, $edit, t('Save content type'));
+      $this->assertRaw(t('The content type %type has been updated.', array('%type' => $ief_content_type)), t('%type content type has been updated.', array('%type' => $ief_content_type)));
+    }
+
+    // Make the fields of the ief_reference_type multilingual.
+    $edit = array();
+    $edit['field[translatable]'] = 1;
+    $this->drupalPost('admin/structure/types/manage/ief_reference_type/fields/field_first_name', $edit, t('Save settings'));
+    $this->assertRaw(t('Saved %field configuration.', array('%field' => 'First name')), t('field_first_name field settings have been updated.'));
+    $this->drupalPost('admin/structure/types/manage/ief_reference_type/fields/field_last_name', $edit, t('Save settings'));
+    $this->assertRaw(t('Saved %field configuration.', array('%field' => 'Last name')), t('field_last_name field settings have been updated.'));
+
+    // Change the display of the entity reference to display the rendered
+    // entity.
+    $edit_field = array(
+      'fields[field_multiple_nodes][type]' => 'entityreference_entity_view',
+      'refresh_rows' => 'field_multiple_nodes',
+    );
+    $this->drupalGet('admin/structure/types/manage/ief_test_multiple/display');
+    $this->drupalPostAJAX(NULL, $edit_field, array('op' => t('Refresh')));
+    $this->drupalPost(NULL, array(), t('Save'));
+
+    $edit_field = array(
+      'fields[field_multiple_nodes_translate][type]' => 'entityreference_entity_view',
+      'refresh_rows' => 'field_multiple_nodes_translate',
+    );
+    $this->drupalGet('admin/structure/types/manage/ief_test_multiple/display');
+    $this->drupalPostAJAX(NULL, $edit_field, array('op' => t('Refresh')));
+    $this->drupalPost(NULL, array(), t('Save'));
+
+  }
+
+  /**
+   * Tests translating inline entities.
+   */
+  public function testEntityTranslation() {
+    $language_list = language_list();
+
+    // Get a node create form.
+    // Create a new node using IEF from a non-translatable field.
+    $this->drupalGet($this->formContentAddUrl);
+    $target_node_from_untranslatable_field_title = $this->randomName();
+    $edit_en = array(
+      'field_multiple_nodes[und][form][title]' => $target_node_from_untranslatable_field_title,
+      'field_multiple_nodes[und][form][field_first_name][en][0][value]' => 'John ' . $target_node_from_untranslatable_field_title,
+      'field_multiple_nodes[und][form][field_last_name][en][0][value]' => 'Doe ' . $target_node_from_untranslatable_field_title,
+    );
+    $this->drupalPostAjax(NULL, $edit_en, $this->getButtonName('//input[@type="submit" and @id="edit-field-multiple-nodes-und-form-actions-ief-add-save"]'));
+    // Create a new node using IEF from a translatable field.
+    $target_node_from_translatable_field_title_en = $this->randomName();
+    $edit_en = array(
+      'field_multiple_nodes_translate[en][form][title]' => $target_node_from_translatable_field_title_en,
+      'field_multiple_nodes_translate[en][form][field_first_name][en][0][value]' => 'John ' . $target_node_from_translatable_field_title_en,
+      'field_multiple_nodes_translate[en][form][field_last_name][en][0][value]' => 'Doe ' . $target_node_from_translatable_field_title_en,
+    );
+    $this->drupalPostAjax(NULL, $edit_en, $this->getButtonName('//input[@type="submit" and @id="edit-field-multiple-nodes-translate-en-form-actions-ief-add-save"]'));
+
+    // Save the parent node, giving it a title.
+    $edit_parent = array(
+      'title' => 'Source Multilingual Node',
+    );
+    $this->drupalPost(NULL, $edit_parent, t('Save'));
+    $title = reset($edit_parent);
+    $node = $this->drupalGetNodeByTitle($title);
+
+    // Translate the parent node, via IEF.
+    $this->drupalGet('node/' . $node->nid . '/edit/add/en/de');
+    // Add a translation  via IEF to the node referenced by the untranslatable field.
+    $this->drupalPostAJAX(NULL, array(), $this->getButtonName('//input[@type="submit" and @id="edit-field-multiple-nodes-und-entities-0-actions-ief-entity-edit"]'));
+    $edit_de = array(
+      'field_multiple_nodes[und][entities][0][form][field_first_name][de][0][value]' => 'Max ' . $target_node_from_untranslatable_field_title,
+      'field_multiple_nodes[und][entities][0][form][field_last_name][de][0][value]' => 'Muster ' . $target_node_from_untranslatable_field_title,
+    );
+    $this->drupalPostAJAX(NULL, $edit_de, $this->getButtonName('//input[@type="submit" and @id="edit-field-multiple-nodes-und-entities-0-form-actions-ief-edit-save"]'));
+    // Create a new node using IEF, in German, via the translatable field.
+    $target_node_from_translatable_field_title_de = $this->randomName();
+    $edit_de = array(
+      'field_multiple_nodes_translate[de][form][title]' => $target_node_from_translatable_field_title_de,
+      'field_multiple_nodes_translate[de][form][field_first_name][de][0][value]' => 'Max ' . $target_node_from_translatable_field_title_de,
+      'field_multiple_nodes_translate[de][form][field_last_name][de][0][value]' => 'Muster ' . $target_node_from_translatable_field_title_de,
+    );
+    $this->drupalPostAjax(NULL, $edit_de, $this->getButtonName('//input[@type="submit" and @id="edit-field-multiple-nodes-translate-de-form-actions-ief-add-save"]'));
+    $this->drupalPost(NULL, array(), t('Save'));
+
+    // Check the parent node's display in English.
+    $this->drupalGet('node/' . $node->nid);
+    $this->assertText('John ' . $target_node_from_untranslatable_field_title);
+    $this->assertText('Doe ' . $target_node_from_untranslatable_field_title);
+    $this->assertText('John ' . $target_node_from_translatable_field_title_en);
+    $this->assertText('Doe ' . $target_node_from_translatable_field_title_en);
+
+    // Check the parent node's display in German.
+    $this->drupalGet('node/' . $node->nid, array('language' => $language_list['de']));
+    $this->assertText('Max ' . $target_node_from_untranslatable_field_title);
+    $this->assertText('Muster ' . $target_node_from_untranslatable_field_title);
+    $this->assertText('Max ' . $target_node_from_translatable_field_title_de);
+    $this->assertText('Muster ' . $target_node_from_translatable_field_title_de);
+
+    // Check the parent form's edit values in English.
+    $this->drupalGet('node/' . $node->nid . '/edit');
+    $this->drupalPostAjax(NULL, array(), $this->getButtonName('//input[@type="submit" and @id="edit-field-multiple-nodes-und-entities-0-actions-ief-entity-edit"]'));
+    $this->assertFieldById('edit-field-multiple-nodes-und-entities-0-form-field-first-name-en-0-value', 'John ' . $target_node_from_untranslatable_field_title);
+    $this->assertFieldById('edit-field-multiple-nodes-und-entities-0-form-field-last-name-en-0-value', 'Doe ' . $target_node_from_untranslatable_field_title);
+    $this->drupalPostAjax(NULL, array(), $this->getButtonName('//input[@type="submit" and @id="edit-field-multiple-nodes-translate-en-entities-0-actions-ief-entity-edit"]'));
+    $this->assertFieldById('edit-field-multiple-nodes-translate-en-entities-0-form-field-first-name-en-0-value', 'John ' . $target_node_from_translatable_field_title_en);
+    $this->assertFieldById('edit-field-multiple-nodes-translate-en-entities-0-form-field-last-name-en-0-value', 'Doe ' . $target_node_from_translatable_field_title_en);
+
+    // Check the parent form's edit values in German.
+    $this->drupalGet('node/' . $node->nid . '/edit', array('language' => $language_list['de']));
+    $this->drupalPostAjax(NULL, array(), $this->getButtonName('//input[@type="submit" and  @id="edit-field-multiple-nodes-und-entities-0-actions-ief-entity-edit"]'));
+    $this->assertFieldById('edit-field-multiple-nodes-und-entities-0-form-field-first-name-de-0-value', 'Max ' . $target_node_from_untranslatable_field_title);
+    $this->assertFieldById('edit-field-multiple-nodes-und-entities-0-form-field-last-name-de-0-value', 'Muster ' . $target_node_from_untranslatable_field_title);
+    $this->drupalPostAJAX(NULL, array(), $this->getButtonName('//input[@type="submit" and  @id="edit-field-multiple-nodes-translate-de-entities-0-actions-ief-entity-edit"]'));
+    $this->assertFieldById('edit-field-multiple-nodes-translate-de-entities-0-form-field-first-name-de-0-value', 'Max ' . $target_node_from_translatable_field_title_de);
+    $this->assertFieldById('edit-field-multiple-nodes-translate-de-entities-0-form-field-last-name-de-0-value', 'Muster ' . $target_node_from_translatable_field_title_de);
+  }
+
+}
diff --git a/tests/modules/inline_entity_form_test/inline_entity_form_test.module b/tests/modules/inline_entity_form_test/inline_entity_form_test.module
index 8f46348..76d71fb 100644
--- a/tests/modules/inline_entity_form_test/inline_entity_form_test.module
+++ b/tests/modules/inline_entity_form_test/inline_entity_form_test.module
@@ -146,6 +146,24 @@ function inline_entity_form_test_install() {
   );
   field_create_field($field);
 
+  $field = array(
+    'field_name' => 'field_multiple_nodes_translate',
+    'type' => 'entityreference',
+    'cardinality' => -1,
+    'translatable' => TRUE,
+    'required' => TRUE,
+    'settings' => array(
+      'target_type' => 'node',
+      'handler' => 'base',
+      'handler_settings' => array(
+        'target_bundles' => array(
+          'ief_reference_type' => 'ief_reference_type',
+        ),
+      ),
+    ),
+  );
+  field_create_field($field);
+
   $field_bases['field_positive_int'] = array(
     'active' => 1,
     'cardinality' => 1,
@@ -306,6 +324,31 @@ function inline_entity_form_test_install() {
   field_create_instance($instance);
 
   $instance = array(
+    'bundle' => 'ief_test_multiple',
+    'entity_type' => 'node',
+    'field_name' => 'field_multiple_nodes_translate',
+    'label' => 'Multiple nodes (translatable)',
+    'required' => TRUE,
+    'widget' => array(
+      'type' => 'inline_entity_form',
+      'settings' => array(
+        'fields' => array(),
+        'type_settings' => array(
+          'allow_clone' => 0,
+          'allow_existing' => 0,
+          'allow_new' => 1,
+          'delete_references' => 0,
+          'label_plural' => 'nodes',
+          'label_singular' => 'node',
+          'match_operator' => 'CONTAINS',
+          'override_labels' => 0,
+        ),
+      ),
+    ),
+  );
+  field_create_instance($instance);
+
+  $instance = array(
     'bundle' => 'ief_test_custom',
     'entity_type' => 'node',
     'field_name' => 'field_positive_int',
