diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
index 2c54daa..e13c62a 100644
--- a/core/modules/entity/entity.module
+++ b/core/modules/entity/entity.module
@@ -12,6 +12,11 @@ use Drupal\entity\EntityStorageException;
 use Drupal\entity\EntityInterface;
 
 /**
+ * The type of language used to define the form language.
+ */
+const ENTITY_LANGUAGE_TYPE_FORM = 'entity_language_form';
+
+/**
  * Implements hook_help().
  */
 function entity_help($path, $arg) {
@@ -467,9 +472,10 @@ function entity_form_id(EntityInterface $entity, $operation = 'default') {
  * @return
  *   A $form_state array already filled the entity form controller.
  */
-function entity_form_state_defaults(EntityInterface $entity, $operation = 'default') {
+function entity_form_state_defaults(EntityInterface $entity, $operation = 'default', $langcode = NULL) {
   $form_state = array();
   $controller = entity_form_controller($entity->entityType(), $operation);
+  $form_state['langcode'] = empty($langcode) ? language(LANGUAGE_TYPE_CONTENT)->langcode : $langcode;
   $form_state['build_info']['callback'] = array($controller, 'build');
   $form_state['build_info']['base_form_id'] = $entity->entityType() . '_form';
   $form_state['build_info']['args'] = array($entity);
@@ -506,8 +512,8 @@ function entity_form_submit(EntityInterface $entity, $operation = 'default', &$f
  * @return
  *   The processed form for the given entity and operation.
  */
-function entity_get_form(EntityInterface $entity, $operation = 'default') {
-  $form_state = entity_form_state_defaults($entity, $operation);
+function entity_get_form(EntityInterface $entity, $operation = 'default', $langcode = NULL) {
+  $form_state = entity_form_state_defaults($entity, $operation, $langcode);
   $form_id = entity_form_id($entity, $operation);
   return drupal_build_form($form_id, $form_state);
 }
@@ -556,3 +562,16 @@ function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_st
     field_attach_submit($entity_type, $entity, $form, $form_state);
   }
 }
+
+/**
+ * Implements hook_language_types_info().
+ */
+function entity_language_types_info() {
+  return array(
+    ENTITY_LANGUAGE_TYPE_FORM => array(
+      'name' => t('Form'),
+      'description' => t('Order of language detection methods for form.'),
+      'fixed' => array(LANGUAGE_NEGOTIATION_CONTENT),
+    ),
+  );
+}
diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormController.php b/core/modules/entity/lib/Drupal/entity/EntityFormController.php
index 4f1263c..a611010 100644
--- a/core/modules/entity/lib/Drupal/entity/EntityFormController.php
+++ b/core/modules/entity/lib/Drupal/entity/EntityFormController.php
@@ -208,11 +208,22 @@ class EntityFormController implements EntityFormControllerInterface {
    * Implements Drupal\entity\EntityFormControllerInterface::getFormLangcode().
    */
   public function getFormLangcode($form_state) {
-    // @todo Introduce a new form language type (see hook_language_types_info())
-    // to be used as the default active form language, should it be missing, so
-    // that entity forms can be used to submit multilingual values.
-    $language = $this->getEntity($form_state)->language();
-    return !empty($language->langcode) ? $language->langcode : NULL;
+    $entity = $this->getEntity($form_state);
+    $langcode = FALSE;
+
+    if (language_multilingual()) {
+      $langcode = $form_state['langcode'];
+      $translations = $entity->translations();
+      $fallback = language_fallback_get_candidates(ENTITY_LANGUAGE_TYPE_FORM);
+
+      while (!empty($langcode) && !isset($translations->data[$langcode])) {
+        $langcode = array_shift($fallback);
+      }
+    }
+
+    // If the site is not multilingual or no translation for the given form
+    // language is available, fall back to the entity language.
+    return !empty($langcode) ? $langcode : $entity->language();
   }
 
   /**
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index a94876e..8613aa1 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -410,6 +410,15 @@ function language_language_negotiation_info() {
     'description' => t('Use the detected interface language.'),
   );
 
+  $negotiation_info[LANGUAGE_NEGOTIATION_CONTENT] = array(
+    'types' => array(),
+    'callbacks' => array('negotiation' => 'language_from_content'),
+    'file' => $file,
+    'weight' => 8,
+    'name' => t('Content'),
+    'description' => t('Use the detected content language.'),
+  );
+
   $negotiation_info[LANGUAGE_NEGOTIATION_URL_FALLBACK] = array(
     'types' => array(LANGUAGE_TYPE_URL),
     'callbacks' => array('negotiation' => 'language_url_fallback'),
diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc
index 48a8083..ef90bb9 100644
--- a/core/modules/language/language.negotiation.inc
+++ b/core/modules/language/language.negotiation.inc
@@ -21,6 +21,11 @@ const LANGUAGE_NEGOTIATION_BROWSER = 'language-browser';
 const LANGUAGE_NEGOTIATION_INTERFACE = 'language-interface';
 
 /**
+ * The language is determined using the current content language.
+ */
+const LANGUAGE_NEGOTIATION_CONTENT = 'language-content';
+
+/**
  * If no URL language, language is determined using an already detected one.
  */
 const LANGUAGE_NEGOTIATION_URL_FALLBACK = 'language-url-fallback';
@@ -56,6 +61,16 @@ function language_from_interface() {
 }
 
 /**
+ * Identifies the language from the current content language.
+ *
+ * @return
+ *   The current content language code.
+ */
+function language_from_content() {
+  return language(LANGUAGE_TYPE_CONTENT)->langcode;
+}
+
+/**
  * Identify language from the Accept-language HTTP header we got.
  *
  * We perform browser accept-language parsing only if page cache is disabled,
