Index: modules/aggregator/aggregator.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/aggregator/aggregator.test,v
retrieving revision 1.28
diff -u -p -r1.28 aggregator.test
--- modules/aggregator/aggregator.test	30 Jul 2009 19:24:20 -0000	1.28
+++ modules/aggregator/aggregator.test	7 Aug 2009 20:39:48 -0000
@@ -253,7 +253,7 @@ EOF;
       $edit = array();
       $edit['title'] = $this->randomName();
       $edit['body[0][value]'] = $this->randomName();
-      $this->drupalPost('node/add/article', $edit, t('Save'));
+      $this->drupalPost('node/add/article', $edit, t('Publish'));
     }
   }
 }
Index: modules/blog/blog.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.test,v
retrieving revision 1.17
diff -u -p -r1.17 blog.test
--- modules/blog/blog.test	3 Aug 2009 03:04:33 -0000	1.17
+++ modules/blog/blog.test	7 Aug 2009 20:39:49 -0000
@@ -153,7 +153,7 @@ class BlogTestCase extends DrupalWebTest
       $edit = array();
       $edit['title'] = 'node/' . $node->nid;
       $edit['body[0][value]'] = $this->randomName(256);
-      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
       $this->assertRaw(t('Blog entry %title has been updated.', array('%title' => $edit['title'])), t('Blog node was edited'));
 
       // Delete blog node.
Index: modules/book/book.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.test,v
retrieving revision 1.13
diff -u -p -r1.13 book.test
--- modules/book/book.test	20 Jul 2009 18:51:32 -0000	1.13
+++ modules/book/book.test	7 Aug 2009 20:39:50 -0000
@@ -65,7 +65,7 @@ class BookTestCase extends DrupalWebTest
     $other_book = $this->createBookNode('new');
     $node = $this->createBookNode($book->nid);
     $edit = array('book[bid]' => $other_book->nid);
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
 
     $this->drupalLogout();
     $this->drupalLogin($web_user);
@@ -180,10 +180,10 @@ class BookTestCase extends DrupalWebTest
       $this->drupalPost('node/add/book', $edit, t('Change book (update list of parents)'));
 
       $edit['book[plid]'] = $parent;
-      $this->drupalPost(NULL, $edit, t('Save'));
+      $this->drupalPost(NULL, $edit, t('Publish'));
     }
     else {
-      $this->drupalPost('node/add/book', $edit, t('Save'));
+      $this->drupalPost('node/add/book', $edit, t('Publish'));
     }
 
     // Check to make sure the book node was created.
Index: modules/dblog/dblog.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/dblog/dblog.test,v
retrieving revision 1.24
diff -u -p -r1.24 dblog.test
--- modules/dblog/dblog.test	31 Jul 2009 19:01:01 -0000	1.24
+++ modules/dblog/dblog.test	7 Aug 2009 20:39:53 -0000
@@ -262,14 +262,14 @@ class DBLogTestCase extends DrupalWebTes
     // Create node using form to generate add content event (which is not triggered by drupalCreateNode).
     $edit = $this->getContent($type);
     $title = $edit['title'];
-    $this->drupalPost('node/add/' . $type, $edit, t('Save'));
+    $this->drupalPost('node/add/' . $type, $edit, t('Publish'));
     $this->assertResponse(200);
     // Retrieve node object.
     $node = $this->drupalGetNodeByTitle($title);
     $this->assertTrue($node != NULL, t('Node @title was loaded', array('@title' => $title)));
     // Edit node.
     $edit = $this->getContentUpdate($type);
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
     $this->assertResponse(200);
     // Delete node.
     $this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
Index: modules/field/modules/field_sql_storage/field_sql_storage.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/field_sql_storage/field_sql_storage.module,v
retrieving revision 1.17
diff -u -p -r1.17 field_sql_storage.module
--- modules/field/modules/field_sql_storage/field_sql_storage.module	15 Jul 2009 17:55:18 -0000	1.17
+++ modules/field/modules/field_sql_storage/field_sql_storage.module	7 Aug 2009 20:39:54 -0000
@@ -503,4 +503,4 @@ function field_sql_storage_field_storage
       ->condition('bundle', $bundle_old)
       ->execute();
   }
-}
\ No newline at end of file
+}
Index: modules/filter/filter.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/filter/filter.test,v
retrieving revision 1.28
diff -u -p -r1.28 filter.test
--- modules/filter/filter.test	27 Jul 2009 20:15:35 -0000	1.28
+++ modules/filter/filter.test	7 Aug 2009 20:39:54 -0000
@@ -112,7 +112,7 @@ class FilterAdminTestCase extends Drupal
     $edit['title'] = $this->randomName();
     $edit['body[0][value]'] = $body . '<random>' . $extra_text . '</random>';
     $edit['body[0][value_format]'] = $filtered;
-    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->drupalPost('node/add/page', $edit, t('Publish'));
     $this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Filtered node created.'));
 
     $node = $this->drupalGetNodeByTitle($edit['title']);
Index: modules/forum/forum.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.test,v
retrieving revision 1.27
diff -u -p -r1.27 forum.test
--- modules/forum/forum.test	3 Aug 2009 03:04:33 -0000	1.27
+++ modules/forum/forum.test	7 Aug 2009 20:39:55 -0000
@@ -243,8 +243,7 @@ class ForumTestCase extends DrupalWebTes
     // Instead, the post variables seem to pick up the first non-blank value in the select list.
 
     // Create forum topic.
-//    $this->drupalPost('node/add/forum/' . $forum['tid'], $edit, t('Save'));
-    $this->drupalPost('node/add/forum/', $edit, t('Save'));
+    $this->drupalPost('node/add/forum/', $edit, t('Publish'));
     $type = t('Forum topic');
     if ($container) {
       $this->assertNoRaw(t('@type %title has been created.', array('@type' => $type, '%title' => $title)), t('Forum topic was not created'));
@@ -324,7 +323,7 @@ class ForumTestCase extends DrupalWebTes
       $edit['body[0][value]'] = $this->randomName(256);
       $edit['taxonomy[1]'] = $this->root_forum['tid']; // Assumes the topic is initially associated with $forum.
       $edit['shadow'] = TRUE;
-      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
       $this->assertRaw(t('Forum topic %title has been updated.', array('%title' => $edit['title'])), t('Forum node was edited'));
 
       // Verify topic was moved to a different forum.
Index: modules/node/node.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.admin.inc,v
retrieving revision 1.60
diff -u -p -r1.60 node.admin.inc
--- modules/node/node.admin.inc	30 Jul 2009 19:24:21 -0000	1.60
+++ modules/node/node.admin.inc	7 Aug 2009 20:39:56 -0000
@@ -75,6 +75,7 @@ function node_filters() {
     'options' => array(
       'status-1' => t('published'),
       'status-0' => t('not published'),
+      'draft-1' => t('pending drafts'),
       'promote-1' => t('promoted'),
       'promote-0' => t('not promoted'),
       'sticky-1' => t('sticky'),
@@ -128,6 +129,9 @@ function node_build_filter_query(SelectQ
       case 'language':
         $query->condition('n.' . $key, $value);
         break;
+      case 'draft':
+        $query->innerJoin('node_revision', 'v', 'n.nid = v.nid AND n.timestamp < v.timestamp');
+        break;
     }
   }
 }
@@ -599,4 +603,4 @@ function node_multiple_delete_confirm_su
 function node_modules_installed($modules) {
   // Clear node type cache for node permissions.
   node_type_clear();
-}
\ No newline at end of file
+}
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1092
diff -u -p -r1.1092 node.module
--- modules/node/node.module	5 Aug 2009 15:58:34 -0000	1.1092
+++ modules/node/node.module	7 Aug 2009 20:39:59 -0000
@@ -952,10 +952,14 @@ function node_save($node) {
   if (empty($node->created)) {
     $node->created = REQUEST_TIME;
   }
-  // The changed timestamp is always updated for bookkeeping purposes (revisions, searching, ...)
-  $node->changed = REQUEST_TIME;
-
-  $node->timestamp = REQUEST_TIME;
+  // The changed timestamp is always updated for bookkeeping purposes.
+  if (empty($node->timestamp_changed)) {
+    $node->changed = REQUEST_TIME;
+  }
+  // Set the revision timestamp.
+  if (empty($node->timestamp_revision)) {
+    $node->timestamp = REQUEST_TIME;
+  }
   $update_node = TRUE;
 
   // Generate the node table query and the node_revisions table query.
@@ -1180,7 +1184,6 @@ function node_show($node, $message = FAL
   if ($message) {
     drupal_set_title(t('Revision of %title from %date', array('%title' => $node->title, '%date' => format_date($node->revision_timestamp))), PASS_THROUGH);
   }
-
   // Update the history table, stating that this user viewed this node.
   node_tag_new($node->nid);
 
@@ -1774,6 +1777,14 @@ function node_menu() {
     'weight' => 1,
     'type' => MENU_LOCAL_TASK,
   );
+  $items['node/%/edit/revision/%'] = array(
+    'title' => 'Edit',
+    'page callback' => 'node_revision_page_edit',
+    'page arguments' => array(1, 4),
+    'access callback' => 'node_revision_edit_access',
+    'access arguments' => array(1, 4),
+    'type' => MENU_CALLBACK,
+  );
   $items['node/%node/delete'] = array(
     'title' => 'Delete',
     'page callback' => 'drupal_get_form',
@@ -2322,6 +2333,21 @@ function node_access($op, $node, $accoun
 }
 
 /**
+ * Check access for editing a revision.
+ *
+ * @param $nid
+ *  The node ID.
+ * @param $vid
+ *  The revision ID.
+ * @return
+ *   Whether the user can access the node.
+ */
+function node_revision_edit_access($nid, $vid) {
+  $node = node_load($nid, $vid);
+  return _node_revision_access($node, 'revert');
+}
+
+/**
  * Generate an SQL join clause for use in fetching a node listing.
  *
  * @param $node_alias
Index: modules/node/node.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v
retrieving revision 1.73
diff -u -p -r1.73 node.pages.inc
--- modules/node/node.pages.inc	4 Aug 2009 06:44:48 -0000	1.73
+++ modules/node/node.pages.inc	7 Aug 2009 20:39:59 -0000
@@ -16,6 +16,16 @@ function node_page_edit($node) {
   return drupal_get_form($node->type . '_node_form', $node);
 }
 
+/**
+ * Menu callback to present the node editing form for a revision.
+ */
+function node_revision_page_edit($nid, $vid) {
+  $node = node_load($nid, $vid);
+  $type_name = node_type_get_name($node);
+  drupal_set_title(t('<em>Edit @type</em> @title', array('@type' => $type_name, '@title' => $node->title)), PASS_THROUGH);
+  return drupal_get_form($node->type . '_node_form', $node);
+}
+
 function node_add_page() {
   $item = menu_get_item();
   $content = system_admin_menu_block($item);
@@ -232,9 +242,8 @@ function node_form(&$form_state, $node) 
     '#weight' => 95,
   );
   $form['options']['status'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Published'),
-    '#default_value' => $node->status,
+    '#type' => 'value',
+    '#value' => $node->status,
   );
   $form['options']['promote'] = array(
     '#type' => 'checkbox',
@@ -258,12 +267,19 @@ function node_form(&$form_state, $node) 
   // Add the buttons.
   $form['buttons'] = array();
   $form['buttons']['#weight'] = 100;
-  $form['buttons']['submit'] = array(
+  $form['buttons']['publish'] = array(
     '#type' => 'submit',
     '#access' => variable_get('node_preview_' . $node->type, 1) != DRUPAL_REQUIRED || (!form_get_errors() && isset($form_state['node_preview'])),
-    '#value' => t('Save'),
+    '#value' => t('Publish'),
     '#weight' => 5,
-    '#submit' => array('node_form_submit'),
+    '#submit' => array('node_form_publish_submit'),
+  );
+  $form['buttons']['draft'] = array(
+    '#access' => user_access('access revisions') && user_access('publish revisions') || user_access('administer nodes'),
+    '#type' => 'submit',
+    '#value' => t('Save as draft'),
+    '#weight' => 6,
+    '#submit' => array('node_form_draft_submit'),
   );
   $form['buttons']['preview'] = array(
     '#access' => variable_get('node_preview_' . $node->type, 1) != DRUPAL_DISABLED,
@@ -272,6 +288,13 @@ function node_form(&$form_state, $node) 
     '#weight' => 10,
     '#submit' => array('node_form_build_preview'),
   );
+  $form['buttons']['unpublish'] = array(
+    '#access' => !empty($node->status) && user_access('administer nodes'),
+    '#type' => 'submit',
+    '#value' => t('Unpublish'),
+    '#weight' => 11,
+    '#submit' => array('node_form_unpublish_submit'),
+  );
   if (!empty($node->nid) && node_access('delete', $node)) {
     $form['buttons']['delete'] = array(
       '#type' => 'submit',
@@ -395,6 +418,77 @@ function theme_node_preview($node) {
   return $output;
 }
 
+/**
+ * Submit handler for saving as draft.
+ */
+function node_form_draft_submit($form, &$form_state) {
+  $node = node_form_submit_build_node($form, $form_state);
+
+  // Always create a new revision if saving as a draft.
+  $node->revision = TRUE;
+  if (empty($node->nid)) {
+    $node->status = FALSE;
+  }
+  else {
+    // Set $node->changed to the current value so that this draft does not
+    // affect the 'updated' mark on node listings.
+    $original = node_load($node->nid);
+    $node->timestamp_changed = $original->changed;
+  }
+  node_save($node);
+
+  // If the node is published, and there is already an existing revision
+  // we need to ensure that the data from the current active revision is used
+  // in both the {node} and field API tables.
+  if ($node->status && $node->old_vid) {
+    // Since we have already saved a new revision, load the original again.
+    $current = node_load($node->nid, $node->old_vid);
+
+    // Set taxonomy terms to tids to resolve inconsistencies between loaded
+    // and saved data.
+    if (module_exists('taxonomy')) {
+      $current->taxonomy = array_keys($current->taxonomy);
+    }
+    $current->revision = TRUE;
+
+    // Set both the updated and revision timestamps to those of the revision
+    // we are re-saving to ensure it is listed correctly on the revisions tab.
+    $current->timestamp_updated = $current->timestamp_revision = $original->changed;
+    node_save($current);
+
+    // We now have a duplicate copy of this revision, so delete the old one.
+    // @todo, create node_delete_revision().
+    db_delete('node_revision')
+      ->condition('nid', $original->nid)
+      ->condition('vid', $original->vid)
+      ->execute();
+    module_invoke_all('node_delete_revision', $original);
+    field_attach_delete_revision('node', $original);
+  }
+
+  if ($node->nid) {
+    unset($form_state['rebuild']);
+    $form_state['nid'] = $node->nid;
+    $form_state['redirect'] = 'node/' . $node->nid;
+  }
+}
+
+/**
+ * Submit handler for saving as published.
+ */
+function node_form_publish_submit($form, &$form_state) {
+  $form_state['values']['status'] = 1;
+  node_form_submit($form, $form_state);
+}
+
+/**
+ * Submit handler for saving as unpublished.
+ */
+function node_form_unpublish_submit($form, &$form_state) {
+  $form_state['values']['status'] = 0;
+  node_form_submit($form, $form_state);
+}
+
 function node_form_submit($form, &$form_state) {
   global $user;
 
@@ -480,7 +574,7 @@ function node_delete_confirm_submit($for
 function node_revision_overview($node) {
   drupal_set_title(t('Revisions for %title', array('%title' => $node->title)), PASS_THROUGH);
 
-  $header = array(t('Revision'), array('data' => t('Operations'), 'colspan' => 2));
+  $header = array(t('Revision'), array('data' => t('Operations'), 'colspan' => 3));
 
   $revisions = node_revision_list($node);
 
@@ -501,21 +595,25 @@ function node_revision_overview($node) {
       $row[] = array('data' => t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"), '!username' => theme('username', $revision)))
                                . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : ''),
                      'class' => 'revision-current');
-      $operations[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => 2);
+      $operations[] = array('data' => theme('placeholder', t('current revision')), 'class' => 'revision-current', 'colspan' => 3);
     }
     else {
       $row[] = t('!date by !username', array('!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"), '!username' => theme('username', $revision)))
                . (($revision->log != '') ? '<p class="revision-log">' . filter_xss($revision->log) . '</p>' : '');
       if ($revert_permission) {
-        $operations[] = l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert");
+        $title = $node->changed > $revision->timestamp ? t('revert') : t('publish');
+        $operations[] = l($title, "node/$node->nid/revisions/$revision->vid/revert");
       }
       if ($delete_permission) {
         $operations[] = l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete");
       }
+      if ($revert_permission) {
+        $operations[] = l(t('edit'), "node/$node->nid/edit/revision/$revision->vid");
+      }
     }
     $rows[] = array_merge($row, $operations);
   }
-  
+
   $build['node_revisions_table'] = array(
     '#theme' => 'table',
     '#rows' => $rows,
@@ -530,7 +628,7 @@ function node_revision_overview($node) {
  */
 function node_revision_revert_confirm($form_state, $node_revision) {
   $form['#node_revision'] = $node_revision;
-  return confirm_form($form, t('Are you sure you want to revert to the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel'));
+  return confirm_form($form, t('Are you sure you want to publish the revision from %revision-date?', array('%revision-date' => format_date($node_revision->revision_timestamp))), 'node/' . $node_revision->nid . '/revisions', '', t('Revert'), t('Cancel'));
 }
 
 function node_revision_revert_confirm_submit($form, &$form_state) {
Index: modules/node/node.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.test,v
retrieving revision 1.38
diff -u -p -r1.38 node.test
--- modules/node/node.test	28 Jul 2009 19:18:06 -0000	1.38
+++ modules/node/node.test	7 Aug 2009 20:40:00 -0000
@@ -191,7 +191,7 @@ class PageEditTestCase extends DrupalWeb
     $edit = array();
     $edit['title'] = $this->randomName(8);
     $edit[$body_key] = $this->randomName(16);
-    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->drupalPost('node/add/page', $edit, t('Publish'));
 
     // Check that the node exists in the database.
     $node = $this->drupalGetNodeByTitle($edit['title']);
@@ -213,7 +213,7 @@ class PageEditTestCase extends DrupalWeb
     $edit['title'] = $this->randomName(8);
     $edit[$body_key] = $this->randomName(16);
     // Stay on the current page, without reloading.
-    $this->drupalPost(NULL, $edit, t('Save'));
+    $this->drupalPost(NULL, $edit, t('Publish'));
 
     // Check that the title and body fields are displayed with the updated values.
     $this->assertText($edit['title'], t('Title displayed.'));
@@ -312,7 +312,7 @@ class PageCreationTestCase extends Drupa
     $edit = array();
     $edit['title'] = $this->randomName(8);
     $edit['body[0][value]'] = $this->randomName(16);
-    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->drupalPost('node/add/page', $edit, t('Publish'));
 
     // Check that the page has been created.
     $this->assertRaw(t('!post %title has been created.', array('!post' => 'Page', '%title' => $edit['title'])), t('Page created.'));
@@ -501,7 +501,7 @@ class NodePostSettingsTestCase extends D
     $edit = array();
     $edit['title'] = $this->randomName(8);
     $edit['body[0][value]'] = $this->randomName(16);
-    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->drupalPost('node/add/page', $edit, t('Publish'));
 
     // Check that the post information is displayed.
     $node = $this->drupalGetNodeByTitle($edit['title']);
@@ -522,7 +522,7 @@ class NodePostSettingsTestCase extends D
     $edit = array();
     $edit['title'] = $this->randomName(8);
     $edit['body[0][value]'] = $this->randomName(16);
-    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->drupalPost('node/add/page', $edit, t('Publish'));
 
     // Check that the post information is displayed.
     $node = $this->drupalGetNodeByTitle($edit['title']);
Index: modules/path/path.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/path/path.test,v
retrieving revision 1.16
diff -u -p -r1.16 path.test
--- modules/path/path.test	14 Jul 2009 10:22:17 -0000	1.16
+++ modules/path/path.test	7 Aug 2009 20:40:00 -0000
@@ -214,7 +214,7 @@ class PathLanguageTestCase extends Drupa
     $edit['title'] = $this->randomName();
     $edit['body[0][value]'] = $this->randomName();
     $edit['path'] = $this->randomName();
-    $this->drupalPost(NULL, $edit, t('Save'));
+    $this->drupalPost(NULL, $edit, t('Publish'));
 
     // Clear the path lookup cache.
     drupal_lookup_path('wipe');
Index: modules/php/php.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/php/php.test,v
retrieving revision 1.14
diff -u -p -r1.14 php.test
--- modules/php/php.test	13 Jul 2009 21:51:11 -0000	1.14
+++ modules/php/php.test	7 Aug 2009 20:40:00 -0000
@@ -61,7 +61,7 @@ class PHPFilterTestCase extends PHPTestC
     // Change filter to PHP filter and see that PHP code is evaluated.
     $edit = array();
     $edit['body[0][value_format]'] = 3;
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
     $this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), t('PHP code filter turned on.'));
 
     // Make sure that the PHP code shows up as text.
Index: modules/poll/poll.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.test,v
retrieving revision 1.21
diff -u -p -r1.21 poll.test
--- modules/poll/poll.test	20 Jul 2009 18:51:33 -0000	1.21
+++ modules/poll/poll.test	7 Aug 2009 20:40:01 -0000
@@ -44,7 +44,7 @@ class PollTestCase extends DrupalWebTest
       list($edit, $index) = $this->_pollGenerateEdit($title, $choices, $index);
     }
 
-    $this->drupalPost(NULL, $edit, t('Save'));
+    $this->drupalPost(NULL, $edit, t('Publish'));
     $node = $this->drupalGetNodeByTitle($title);
     $this->assertText(t('@type @title has been created.', array('@type' => node_type_get_name('poll'), '@title' => $title)), 'Poll has been created.');
     $this->assertTrue($node->nid, t('Poll has been found in the database.'));
@@ -79,7 +79,7 @@ class PollTestCase extends DrupalWebTest
 
   function pollUpdate($nid, $title, $edit) {
     // Edit the poll node.
-    $this->drupalPost('node/' . $nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $nid . '/edit', $edit, t('Publish'));
     $this->assertText(t('@type @title has been updated.', array('@type' => node_type_get_name('poll'), '@title' => $title)), 'Poll has been updated.');
   }
 }
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.62
diff -u -p -r1.62 system.test
--- modules/system/system.test	5 Aug 2009 16:16:41 -0000	1.62
+++ modules/system/system.test	7 Aug 2009 20:40:12 -0000
@@ -701,7 +701,7 @@ class PageTitleFiltering extends DrupalW
      'body[0][value]' => '!SimpleTest! test body' . $this->randomName(200),
     );
     // Create the node with HTML in the title.
-    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->drupalPost('node/add/page', $edit, t('Publish'));
 
     $node = $this->drupalGetNodeByTitle($edit['title']);
     $this->assertNotNull($node, 'Node created and found in database');
Index: modules/taxonomy/taxonomy.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v
retrieving revision 1.43
diff -u -p -r1.43 taxonomy.test
--- modules/taxonomy/taxonomy.test	4 Aug 2009 06:50:07 -0000	1.43
+++ modules/taxonomy/taxonomy.test	7 Aug 2009 20:40:12 -0000
@@ -455,7 +455,7 @@ class TaxonomyTermTestCase extends Taxon
     $edit['title'] = $this->randomName();
     $edit['body[0][value]'] = $this->randomName();
     $edit['taxonomy[' . $this->vocabulary->vid . ']'] = $term1->tid;
-    $this->drupalPost('node/add/article', $edit, t('Save'));
+    $this->drupalPost('node/add/article', $edit, t('Publish'));
 
     // Check that the term is displayed when the node is viewed.
     $node = $this->drupalGetNodeByTitle($edit['title']);
@@ -464,7 +464,7 @@ class TaxonomyTermTestCase extends Taxon
 
     // Edit the node with a different term.
     $edit['taxonomy[' . $this->vocabulary->vid . ']'] = $term2->tid;
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
 
     $this->drupalGet('node/' . $node->nid);
     $this->assertText($term2->name, t('Term is displayed when viewing the node.'));
@@ -496,7 +496,7 @@ class TaxonomyTermTestCase extends Taxon
     // free-tagging field created by the default profile.
     $edit['taxonomy[tags][' . $this->vocabulary->vid . ']'] =  implode(', ', $terms);
     $edit['body[0][value]'] = $this->randomName();
-    $this->drupalPost('node/add/article', $edit, t('Save'));
+    $this->drupalPost('node/add/article', $edit, t('Publish'));
     $this->assertRaw(t('@type %title has been created.', array('@type' => t('Article'), '%title' => $edit['title'])), t('The node was created successfully'));
     foreach ($terms as $term) {
       $this->assertText($term, t('The term was saved and appears on the node page'));
Index: modules/translation/translation.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/translation/translation.test,v
retrieving revision 1.14
diff -u -p -r1.14 translation.test
--- modules/translation/translation.test	20 Jul 2009 18:51:34 -0000	1.14
+++ modules/translation/translation.test	7 Aug 2009 20:40:12 -0000
@@ -61,7 +61,7 @@ class TranslationTestCase extends Drupal
     $edit = array();
     $edit['title'] = $this->randomName();
     $edit['body[0][value]'] = $this->randomName();
-    $this->drupalPost('node/add/page', $edit, t('Save'), array('query' => array('translation' => $node->nid, 'language' => 'es')));
+    $this->drupalPost('node/add/page', $edit, t('Publish'), array('query' => array('translation' => $node->nid, 'language' => 'es')));
     $duplicate = $this->drupalGetNodeByTitle($edit['title']);
     $this->assertEqual($duplicate->tnid, 0, t('The node does not have a tnid.'));
 
@@ -69,7 +69,7 @@ class TranslationTestCase extends Drupal
     $edit = array();
     $edit['body[0][value]'] = $this->randomName();
     $edit['translation[retranslate]'] = TRUE;
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
     $this->assertRaw(t('Page %title has been updated.', array('%title' => $node_title)), t('Original node updated.'));
 
     // Check to make sure that interface shows translation as outdated
@@ -80,7 +80,7 @@ class TranslationTestCase extends Drupal
     $edit = array();
     $edit['body[0][value]'] = $this->randomName();
     $edit['translation[status]'] = FALSE;
-    $this->drupalPost('node/' . $node_translation->nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $node_translation->nid . '/edit', $edit, t('Publish'));
     $this->assertRaw(t('Page %title has been updated.', array('%title' => $node_translation_title)), t('Translated node updated.'));
   }
 
@@ -130,7 +130,7 @@ class TranslationTestCase extends Drupal
     $edit['title'] = $title;
     $edit['body[0][value]'] = $body;
     $edit['language'] = $language;
-    $this->drupalPost('node/add/page', $edit, t('Save'));
+    $this->drupalPost('node/add/page', $edit, t('Publish'));
     $this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Page created.'));
 
     // Check to make sure the node was created.
@@ -154,7 +154,7 @@ class TranslationTestCase extends Drupal
     $edit = array();
     $edit['title'] = $title;
     $edit['body[0][value]'] = $body;
-    $this->drupalPost(NULL, $edit, t('Save'));
+    $this->drupalPost(NULL, $edit, t('Publish'));
     $this->assertRaw(t('Page %title has been created.', array('%title' => $edit['title'])), t('Translation created.'));
 
     // Check to make sure that translation was successful.
Index: modules/trigger/trigger.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/trigger/trigger.test,v
retrieving revision 1.15
diff -u -p -r1.15 trigger.test
--- modules/trigger/trigger.test	28 Jul 2009 19:18:08 -0000	1.15
+++ modules/trigger/trigger.test	7 Aug 2009 20:40:12 -0000
@@ -39,8 +39,14 @@ class TriggerContentTestCase extends Dru
       $edit = array();
       $edit['title'] = '!SimpleTest test node! ' . $this->randomName(10);
       $edit['body[0][value]'] = '!SimpleTest test body! ' . $this->randomName(32) . ' ' . $this->randomName(32);
-      $edit[$info['property']] = !$info['expected'];
-      $this->drupalPost('node/add/page', $edit, t('Save'));
+      if ($action == 'node_publish_action' || $action == 'node_unpublish_action') {
+        $button = $info['button'];
+      }
+      else {
+        $edit[$info['property']] = !$info['expected'];
+      }
+      $button = isset($button) ? $button : t('Save');
+      $this->drupalPost('node/add/page', $edit, $button);
       // Make sure the text we want appears.
       $this->assertRaw(t('!post %title has been created.', array('!post' => 'Page', '%title' => $edit['title'])), t('Make sure the page has actually been created'));
       // Action should have been fired.
@@ -79,11 +85,13 @@ class TriggerContentTestCase extends Dru
         'property' => 'status',
         'expected' => 1,
         'name' => t('publish post'),
+        'button' => t('Publish'),
       ),
       'node_unpublish_action' => array(
         'property' => 'status',
         'expected' => 0,
         'name' => t('unpublish post'),
+        'button' => t('Unpublish'),
       ),
       'node_make_sticky_action' => array(
         'property' => 'sticky',
Index: modules/upload/upload.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.test,v
retrieving revision 1.22
diff -u -p -r1.22 upload.test
--- modules/upload/upload.test	28 Jul 2009 19:18:08 -0000	1.22
+++ modules/upload/upload.test	7 Aug 2009 20:40:12 -0000
@@ -73,7 +73,7 @@ class UploadTestCase extends DrupalWebTe
       // Rename file.
       $edit = array();
       $edit['files[' . $upload->fid . '][description]'] = $new_name = substr($upload->description, 1);
-      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
       $this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), 'File renamed successfully.');
 
       $this->assertText($new_name, $new_name . ' found on node.');
@@ -82,7 +82,7 @@ class UploadTestCase extends DrupalWebTe
       // Delete a file.
       $edit = array();
       $edit['files[' . $upload->fid . '][remove]'] = TRUE;
-      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+      $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
       $this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), 'File deleted successfully.');
 
       $this->assertNoText($new_name, $new_name . ' not found on node.');
@@ -193,7 +193,7 @@ class UploadTestCase extends DrupalWebTe
   function uploadFile($node, $filename, $assert = TRUE) {
     $edit = array();
     $edit['files[upload]'] = $filename; //edit-upload
-    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
+    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Publish'));
     if ($assert) {
       $this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), 'File attached successfully.');
     }
