Index: modules/field/field.attach.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v
retrieving revision 1.59
diff -u -p -r1.59 field.attach.inc
--- modules/field/field.attach.inc	8 Nov 2009 19:11:56 -0000	1.59
+++ modules/field/field.attach.inc	27 Nov 2009 10:45:43 -0000
@@ -493,6 +493,9 @@ function field_attach_form($obj_type, $o
   $form['#pre_render'][] = '_field_extra_weights_pre_render';
   $form['#extra_fields'] = field_extra_fields($bundle);
 
+  // Save the original object to allow later re-use.
+  $form_state['storage']['object'] = $object;
+
   // Let other modules make changes to the form.
   // Avoid module_invoke_all() to let parameters be taken by reference.
   foreach (module_implements('field_attach_form') as $module) {
Index: modules/field/field.default.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.default.inc,v
retrieving revision 1.23
diff -u -p -r1.23 field.default.inc
--- modules/field/field.default.inc	9 Nov 2009 18:23:41 -0000	1.23
+++ modules/field/field.default.inc	27 Nov 2009 10:46:18 -0000
@@ -24,13 +24,25 @@ function field_default_extract_form_valu
 function field_default_submit($obj_type, $object, $field, $instance, $langcode, &$items, $form, &$form_state) {
   $field_name = $field['field_name'];
 
-  // Reorder items to account for drag-n-drop reordering.
-  if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
-    $items = _field_sort_items($field, $items);
-  }
+  if (isset($form_state['values'][$field_name][$langcode])) {
+    // Prepare form submitted values.
 
-  // Filter out empty values.
-  $items = field_set_empty($field, $items);
+    // Reorder items to account for drag-n-drop reordering.
+    if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
+      $items = _field_sort_items($field, $items);
+    }
+    // Filter out empty values.
+    $items = field_set_empty($field, $items);
+  }
+  elseif (!empty($object->revision) && isset($form_state['storage']['object']->{$field_name}[$langcode])) {
+    // To ensure new revisions are created with all field values in all
+    // languages, populate values not included in the form with the ones from
+    // the original object. This covers:
+    // - partial forms including only a subset of the fields,
+    // - fields for which the user has no edit access,
+    // - languages not involved in the form.
+    $items = $form_state['storage']['object']->{$field_name}[$langcode];
+  }
 }
 
 /**
Index: modules/field/field.form.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.form.inc,v
retrieving revision 1.35
diff -u -p -r1.35 field.form.inc
--- modules/field/field.form.inc	20 Nov 2009 04:51:27 -0000	1.35
+++ modules/field/field.form.inc	27 Nov 2009 10:45:43 -0000
@@ -15,20 +15,10 @@ function field_default_form($obj_type, $
   if ($object) {
     list($id, , ) = entity_extract_ids($obj_type, $object);
   }
+  $addition = array();
 
   $field_name = $field['field_name'];
 
-  // Put field information at the top of the form, so that it can be easily
-  // retrieved.
-  // Note : widgets and other form handling code should *always* fetch field
-  // and instance information from $form['#fields'] rather than from
-  // field_info_field(). This lets us build forms for 'variants' of a field,
-  // for instance on admin screens.
-  $form['#fields'][$field_name] = array(
-    'field' => $field,
-    'instance' => $instance,
-  );
-
   // Populate widgets with default values when creating a new object.
   if (empty($items) && empty($id)) {
     $items = field_get_default_value($obj_type, $object, $field, $instance, $langcode);
@@ -78,6 +68,18 @@ function field_default_form($obj_type, $
   }
 
   if ($field_elements) {
+    // Put field information at the top of the form, so that it can be easily
+    // retrieved.
+    // Note: widgets and other form handling code should *always* fetch field
+    // and instance information from $form['#fields'] rather than from
+    // field_info_field(). This lets us build forms for 'variants' of a field,
+    // for instance on admin screens.
+    $form['#fields'][$field_name] = array(
+      'field' => $field,
+      'instance' => $instance,
+      'form_path' => array($field_name),
+    );
+
     // Add the field form element as a child keyed by language code to match
     // the field data structure:
     // $object->{$field_name}[$langcode][$delta][$column].
@@ -101,23 +103,7 @@ function field_default_form($obj_type, $
       $langcode => $field_elements,
     );
   }
-  else {
-    // The field is not accessible, or the widget did not return anything. Make
-    // sure the items are available in the submitted form values.
-    foreach ($items as $delta => $item) {
-      $field_elements[$delta] = array(
-        '#type' => 'value',
-        '#value' => $item,
-      );
-    }
-    $addition[$field_name] = array(
-      '#tree' => TRUE,
-      '#language' => $langcode,
-      $langcode => $field_elements,
-    );
-  }
 
-  $form['#fields'][$field_name]['form_path'] = array($field_name);
 
   return $addition;
 }
Index: modules/field/tests/field.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field.test,v
retrieving revision 1.3
diff -u -p -r1.3 field.test
--- modules/field/tests/field.test	21 Nov 2009 14:35:05 -0000	1.3
+++ modules/field/tests/field.test	27 Nov 2009 11:16:20 -0000
@@ -2521,6 +2521,51 @@ class FieldTranslationsTestCase extends 
       $this->assertTrue($result, t('%language translation correctly handled.', array('%language' => $langcode)));
     }
   }
+
+  /**
+   * Tests field translations when creating a new revision.
+   */
+  function testFieldFormTranslationRevisions() {
+    $web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content'));
+    $this->drupalLogin($web_user);
+
+    // Prepare the field translations.
+    field_test_entity_info_translatable($this->obj_type, TRUE);
+    $eid = 1;
+    $entity = field_test_create_stub_entity($eid, $eid, $this->instance['bundle']);
+    $available_languages = array_flip(field_multilingual_available_languages($this->obj_type, $this->field));
+    unset($available_languages[FIELD_LANGUAGE_NONE]);
+    $field_name = $this->field['field_name'];
+
+    // Store the field translations.
+    $entity->is_new = TRUE;
+    foreach ($available_languages as $langcode => $value) {
+      $entity->{$field_name}[$langcode][0]['value'] = $value + 1;
+    }
+    field_test_entity_save($entity);
+
+    // Create a new revision.
+    $langcode = field_multilingual_valid_language(NULL);
+    $edit = array("{$field_name}[$langcode][0][value]" => $entity->{$field_name}[$langcode][0]['value'], 'revision' => TRUE);
+    $this->drupalPost('test-entity/' . $eid . '/edit', $edit, t('Save'));
+
+    // Check translation revisions.
+    $this->checkTranslationRevisions($eid, $eid, $available_languages);
+    $this->checkTranslationRevisions($eid, $eid + 1, $available_languages);
+  }
+
+  /**
+   * Check if the field translation attached to the entity revision identified
+   * by the passed arguments were correctly stored.
+   */
+  private function checkTranslationRevisions($eid, $evid, $available_languages) {
+    $field_name = $this->field['field_name'];
+    $entity = field_test_entity_test_load($eid, $evid);
+    foreach ($available_languages as $langcode => $value) {
+      $passed = isset($entity->{$field_name}[$langcode]) && $entity->{$field_name}[$langcode][0]['value'] == $value + 1;
+      $this->assertTrue($passed, t('The @language translation for revision @revision was correctly stored', array('@language' => $langcode, '@revision' => $entity->ftvid)));
+    }
+  }
 }
 
 /**
Index: modules/field/tests/field_test.entity.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/tests/field_test.entity.inc,v
retrieving revision 1.1
diff -u -p -r1.1 field_test.entity.inc
--- modules/field/tests/field_test.entity.inc	20 Nov 2009 23:29:28 -0000	1.1
+++ modules/field/tests/field_test.entity.inc	27 Nov 2009 10:45:43 -0000
@@ -154,11 +154,19 @@ function field_test_create_stub_entity($
 function field_test_entity_test_load($ftid, $ftvid = NULL) {
   // Load basic strucure.
   $query = db_select('test_entity', 'fte', array())
-    ->fields('fte')
-    ->condition('ftid', $ftid);
+    ->condition('fte.ftid', $ftid);
+
   if ($ftvid) {
-    $query->condition('ftvid', $ftvid);
+    $query->join('test_entity_revision', 'fter', 'fte.ftid = fter.ftid');
+    $query->addField('fte', 'ftid');
+    $query->addField('fte', 'fttype');
+    $query->addField('fter', 'ftvid');
+    $query->condition('fter.ftvid', $ftvid);
+  }
+  else {
+    $query->fields('fte');
   }
+
   $entities = $query->execute()->fetchAllAssoc('ftid');
 
   // Attach fields.
