diff --git a/includes/common.inc b/includes/common.inc
index ce08390..45d5016 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -7759,6 +7759,37 @@ function entity_label($entity_type, $entity) {
 }
 
 /**
+ * Returns the language of an entity.
+ *
+ * @param $entity_type
+ *   The entity type; e.g., 'node' or 'user'.
+ * @param $entity
+ *   The entity for which to get the language.
+ *
+ * @return
+ *   The entity language, or NULL if not found.
+ */
+function entity_language($entity_type, $entity) {
+  $info = entity_get_info($entity_type);
+
+  // Invoke the callback to get the language. If there is no callback, try
+  // to get it from a property of the entity, otherwise NULL.
+  if (isset($info['language callback']) && function_exists($info['language callback'])) {
+    $langcode = $info['language callback']($entity_type, $entity);
+  }
+  elseif (!empty($info['entity keys']['language']) && isset($entity->{$info['entity keys']['language']})) {
+    $langcode = $entity->{$info['entity keys']['language']};
+  }
+  else {
+    // @todo The right value for D8 should be LANGUAGE_NONE, we cannot use it
+    // here to preserve backward compatibility.
+    $langcode = NULL;
+  }
+
+  return $langcode;
+}
+
+/**
  * Helper function for attaching field API validation to entity forms.
  */
 function entity_form_field_validate($entity_type, $form, &$form_state) {
diff --git a/modules/file/file.module b/modules/file/file.module
index ebf80e9..54a8648 100644
--- a/modules/file/file.module
+++ b/modules/file/file.module
@@ -256,20 +256,17 @@ function file_ajax_upload() {
     return array('#type' => 'ajax', '#commands' => $commands);
   }
 
-  // Get the current element and count the number of files.
-  $current_element = $form;
-  foreach ($form_parents as $parent) {
-    $current_element = $current_element[$parent];
-  }
-  $current_file_count = isset($current_element['#file_upload_delta']) ? $current_element['#file_upload_delta'] : 0;
-
   // Process user input. $form and $form_state are modified in the process.
   drupal_process_form($form['#form_id'], $form, $form_state);
 
-  // Retrieve the element to be rendered.
+  // Get the current element and count the number of files and retrieve the
+  // element to be rendered.
+  $current_element = $form;
   foreach ($form_parents as $parent) {
+    $current_element = $current_element[$parent];
     $form = $form[$parent];
   }
+  $current_file_count = isset($current_element['#file_upload_delta']) ? $current_element['#file_upload_delta'] : 0;
 
   // Add the special Ajax class if a new file was added.
   if (isset($form['#file_upload_delta']) && $current_file_count < $form['#file_upload_delta']) {
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index 5de8e44..b14d4bc 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -395,7 +395,7 @@ function locale_form_node_form_alter(&$form, &$form_state) {
 function locale_field_node_form_submit($form, &$form_state) {
   if (field_has_translation_handler('node', 'locale')) {
     $node = (object) $form_state['values'];
-    $available_languages = field_content_languages();
+    $current_language = entity_language('node', $node);
     list(, , $bundle) = entity_extract_ids('node', $node);
 
     foreach (field_info_instances('node', $bundle) as $instance) {
@@ -405,8 +405,8 @@ function locale_field_node_form_submit($form, &$form_state) {
 
       // Handle a possible language change: new language values are inserted,
       // previous ones are deleted.
-      if ($field['translatable'] && $previous_language != $node->language) {
-        $form_state['values'][$field_name][$node->language] = $node->{$field_name}[$previous_language];
+      if ($field['translatable'] && $previous_language != $current_language) {
+        $form_state['values'][$field_name][$current_language] = $node->{$field_name}[$previous_language];
         $form_state['values'][$field_name][$previous_language] = array();
       }
     }
diff --git a/modules/node/node.pages.inc b/modules/node/node.pages.inc
index 89a1593..31d396a 100644
--- a/modules/node/node.pages.inc
+++ b/modules/node/node.pages.inc
@@ -299,7 +299,7 @@ function node_form($form, &$form_state, $node) {
   }
   $form += array('#submit' => array());
 
-  field_attach_form('node', $node, $form, $form_state, $node->language);
+  field_attach_form('node', $node, $form, $form_state, entity_language('node', $node));
   return $form;
 }
 
diff --git a/modules/path/path.module b/modules/path/path.module
index 86b714d..e1ed541 100644
--- a/modules/path/path.module
+++ b/modules/path/path.module
@@ -97,8 +97,9 @@ function path_form_node_form_alter(&$form, $form_state) {
   $path = array();
   if (!empty($form['#node']->nid)) {
     $conditions = array('source' => 'node/' . $form['#node']->nid);
-    if ($form['#node']->language != LANGUAGE_NONE) {
-      $conditions['language'] = $form['#node']->language;
+    $langcode = entity_language('node', $form['#node']);
+    if ($langcode != LANGUAGE_NONE) {
+      $conditions['language'] = $langcode;
     }
     $path = path_load($conditions);
     if ($path === FALSE) {
@@ -109,7 +110,7 @@ function path_form_node_form_alter(&$form, $form_state) {
     'pid' => NULL,
     'source' => isset($form['#node']->nid) ? 'node/' . $form['#node']->nid : NULL,
     'alias' => '',
-    'language' => isset($form['#node']->language) ? $form['#node']->language : LANGUAGE_NONE,
+    'language' => isset($langcode) ? $langcode : LANGUAGE_NONE,
   );
 
   $form['path'] = array(
@@ -188,8 +189,9 @@ function path_node_insert($node) {
     // Only save a non-empty alias.
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
+      $langcode = entity_language('node', $node);
       $path['source'] = 'node/' . $node->nid;
-      $path['language'] = isset($node->language) ? $node->language : LANGUAGE_NONE;
+      $path['language'] = isset($langcode) ? $langcode : LANGUAGE_NONE;
       path_save($path);
     }
   }
@@ -206,13 +208,7 @@ function path_node_update($node) {
     if (!empty($path['pid']) && empty($path['alias'])) {
       path_delete($path['pid']);
     }
-    // Only save a non-empty alias.
-    if (!empty($path['alias'])) {
-      // Ensure fields for programmatic executions.
-      $path['source'] = 'node/' . $node->nid;
-      $path['language'] = isset($node->language) ? $node->language : LANGUAGE_NONE;
-      path_save($path);
-    }
+    path_node_insert($node);
   }
 }
 
@@ -230,7 +226,10 @@ function path_node_delete($node) {
 function path_form_taxonomy_form_term_alter(&$form, $form_state) {
   // Make sure this does not show up on the delete confirmation form.
   if (empty($form_state['confirm_delete'])) {
-    $path = (isset($form['#term']['tid']) ? path_load('taxonomy/term/' . $form['#term']['tid']) : array());
+    $langcode = entity_language('taxonomy_term', (object) $form['#term']);
+    $langcode = !empty($langcode) ? $langcode : LANGUAGE_NONE;
+    $conditions = array('source' => 'taxonomy/term/' . $form['#term']['tid'], 'language' => $langcode);
+    $path = (isset($form['#term']['tid']) ? path_load($conditions) : array());
     if ($path === FALSE) {
       $path = array();
     }
@@ -238,7 +237,7 @@ function path_form_taxonomy_form_term_alter(&$form, $form_state) {
       'pid' => NULL,
       'source' => isset($form['#term']['tid']) ? 'taxonomy/term/' . $form['#term']['tid'] : NULL,
       'alias' => '',
-      'language' => LANGUAGE_NONE,
+      'language' => $langcode,
     );
     $form['path'] = array(
       '#access' => user_access('create url aliases') || user_access('administer url aliases'),
@@ -270,7 +269,8 @@ function path_taxonomy_term_insert($term) {
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
       $path['source'] = 'taxonomy/term/' . $term->tid;
-      $path['language'] = LANGUAGE_NONE;
+      $langcode = entity_language('taxonomy_term', $term);
+      $path['language'] = !empty($langcode) ? $langcode : LANGUAGE_NONE;
       path_save($path);
     }
   }
@@ -291,7 +291,8 @@ function path_taxonomy_term_update($term) {
     if (!empty($path['alias'])) {
       // Ensure fields for programmatic executions.
       $path['source'] = 'taxonomy/term/' . $term->tid;
-      $path['language'] = LANGUAGE_NONE;
+      $langcode = entity_language('taxonomy_term', $term);
+      $path['language'] = !empty($langcode) ? $langcode : LANGUAGE_NONE;
       path_save($path);
     }
   }
diff --git a/modules/taxonomy/taxonomy.admin.inc b/modules/taxonomy/taxonomy.admin.inc
index a236cfe..828fde0 100644
--- a/modules/taxonomy/taxonomy.admin.inc
+++ b/modules/taxonomy/taxonomy.admin.inc
@@ -696,7 +696,8 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary =
     '#value' => isset($term->vocabulary_machine_name) ? $term->vocabulary_machine_name : $vocabulary->name,
   );
 
-  field_attach_form('taxonomy_term', $term, $form, $form_state);
+  $langcode = entity_language('taxonomy_term', $term);
+  field_attach_form('taxonomy_term', $term, $form, $form_state, $langcode);
 
   $form['relations'] = array(
     '#type' => 'fieldset',
