Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.500
diff -u -p -r1.500 form.inc
--- includes/form.inc	4 Oct 2010 18:00:45 -0000	1.500
+++ includes/form.inc	5 Oct 2010 14:12:00 -0000
@@ -1575,7 +1575,7 @@ function form_error(&$element, $message 
  *   was clicked when the form was submitted, as well as the sanitized
  *   $_POST data.
  */
-function form_builder($form_id, $element, &$form_state) {
+function form_builder($form_id, &$element, &$form_state) {
   // Initialize as unprocessed.
   $element['#processed'] = FALSE;
 
@@ -1602,8 +1602,11 @@ function form_builder($form_id, $element
       $element['#action'] = str_replace('http://', 'https://', $base_root) . $element['#action'];
     }
 
-    // Store a complete copy of the form in form_state prior to building the form.
-    $form_state['complete form'] = $element;
+    // Store a reference to the complete form in $form_state prior to building
+    // the form. This allows advanced #process and #after_build callbacks to
+    // perform changes elsewhere in the form.
+    $form_state['complete form'] = &$element;
+
     // Set a flag if we have a correct form submission. This is always TRUE for
     // programmed forms coming from drupal_form_submit(), or if the form_id coming
     // from the POST data is set and matches the current form_id.
@@ -1749,9 +1752,6 @@ function form_builder($form_id, $element
       // @todo Legacy support. Remove in Drupal 8.
       $form_state['clicked_button'] = $form_state['triggering_element'];
     }
-
-    // Update the copy of the complete form for usage in validation handlers.
-    $form_state['complete form'] = $element;
   }
   return $element;
 }
@@ -3033,6 +3033,115 @@ function form_process_tableselect($eleme
 }
 
 /**
+ * Processes a machine-readable name form element.
+ *
+ * @param $element
+ *   The form element to process. Properties used:
+ *   - #machine_name: An associative array containing:
+ *     - exists: A function name to invoke for checking whether a submitted
+ *       machine name value already exists. The submitted value is passed as
+ *       argument. In most cases, an existing API or menu argument loader
+ *       function can be re-used. The callback is only invoked, if the submitted
+ *       value differs from the element's #default_value.
+ *     - source: (optional) The #array_parents of the form element containing
+ *       the human-readable name (i.e., as contained in the $form structure) to
+ *       use as source for the machine name. Defaults to array('name').
+ *     - label: (optional) A text to display as label for the machine name value
+ *       after the human-readable name form element. Defaults to "Machine name".
+ *     - pattern: (optional) A regular expression (without delimiters) matching
+ *       valid characters in the machine name. Defaults to "[^a-z0-9_]+".
+ *     - replace: (optional) A replacement string character to use for invalid
+ *       characters in the machine name. Defaults to '_'. When using a different
+ *       character, #machine_name_pattern needs to be changed accordingly.
+ *   - #maxlength: (optional) Should be set to the maximum allowed length of the
+ *     machine name. Defaults to 64.
+ *   - #disabled: (optional) Should be set to TRUE in case an existing machine
+ *     name must not be changed after initial creation.
+ */
+function form_process_machine_name($element, &$form_state) {
+  // Apply default form element properties.
+  $element += array(
+    '#title' => t('Machine-readable name'),
+    '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
+    '#machine_name' => array(),
+  );
+  // A form element that only wants to set one #machine_name property (usually
+  // 'source' only) would leave all other properties undefined, if the defaults
+  // were defined in hook_element_info(). Therefore, we apply the defaults here.
+  $element['#machine_name'] += array(
+    'source' => array('name'),
+    'target' => '#' . $element['#id'],
+    'label' => t('Machine name'),
+    'pattern' => '[^a-z0-9_]+',
+    'replace' => '_',
+  );
+
+  // The source element defaults to array('name'), but may have been overidden.
+  if (empty($element['#machine_name']['source'])) {
+    return $element;
+  }
+
+  // Retrieve the form element containing the human-readable name from the
+  // complete form in $form_state. By reference, because we need to append
+  // a #field_suffix that will hold the live preview.
+  $key_exists = NULL;
+  $source = drupal_array_get_nested_value($form_state['complete form'], $element['#machine_name']['source'], $key_exists);
+  if (!$key_exists) {
+    return $element;
+  }
+
+  // Append a field suffix to the source form element, which will contain
+  // the live preview of the machine name.
+  $suffix_id = $source['#id'] . '-machine-name-suffix';
+  $suffix = ' <small id="' . $suffix_id . '">&nbsp;</small>';
+  if (!isset($source['#field_suffix'])) {
+    $source['#field_suffix'] = '';
+  }
+  $source['#field_suffix'] .= $suffix;
+  $parents = array_merge($element['#machine_name']['source'], array('#field_suffix'));
+  drupal_array_set_nested_value($form_state['complete form'], $parents, $suffix);
+
+  $element['#machine_name']['suffix'] = '#' . $suffix_id;
+
+  $js_settings = array(
+    'type' => 'setting',
+    'data' => array(
+      'machineName' => array(
+        '#' . $source['#id'] => $element['#machine_name'],
+      ),
+    ),
+  );
+  $element['#attached']['js'][] = 'misc/machine_name.js';
+  $element['#attached']['js'][] = $js_settings;
+
+  return $element;
+}
+
+/**
+ * Form element validation handler for #type 'machine_name'.
+ */
+function form_validate_machine_name(&$element, &$form_state) {
+  // Restrict machine names to appropriate characters.
+  if (preg_match('@' . $element['#machine_name']['pattern'] . '@', $element['#value'])) {
+    if (!isset($element['#machine_name']['error'])) {
+      form_error($element, t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
+    }
+    else {
+      form_error($element, $element['#machine_name']['error']);
+    }
+  }
+  // #maxlength is validated by _form_validate() already.
+
+  // Prevent duplicate machine names.
+  if ($element['#default_value'] !== $element['#value']) {
+    $function = $element['#machine_name']['exists'];
+    if ($function($element['#value'])) {
+      form_error($element, t('This machine-readable name is already in use. It must be unique.'));
+    }
+  }
+}
+
+/**
  * Adds fieldsets to the specified group or adds group members to this
  * fieldset.
  *
Index: misc/machine_name.js
===================================================================
RCS file: misc/machine_name.js
diff -N misc/machine_name.js
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ misc/machine_name.js	17 Sep 2010 17:55:53 -0000
@@ -0,0 +1,104 @@
+// $Id$
+(function ($) {
+
+/**
+ * Attach the auto machine readable name behavior.
+ *
+ * Settings are expected to be an object of elements to process, where the key
+ * is the HTML ID of the source element in the form and the value is an object
+ * defining the following properties:
+ * - target: The HTML ID of the machine name form element.
+ * - suffix: The HTML ID of the machine name preview form element suffix.
+ * - label: The label to display for the machine name preview.
+ * - pattern: A regular expression (without modifiers) matching disallowed
+ *   characters in the machine readable name; e.g., '[^a-z0-9]+'.
+ * - replace: A replacement string to replace disallowed characters; e.g.,
+ *   '-' or '_'.
+ */
+Drupal.behaviors.machineName = {
+  attach: function (context, settings) {
+    var self = this;
+    $.each(settings.machineName, function (source_id, options) {
+      var $source = $(source_id, context).addClass('machine-name-source');
+      var $target = $(options.target, context).addClass('machine-name-target');
+      var $suffix = $(options.suffix, context);
+      var $wrapper = $target.parents('.form-item:first');
+      // All elements are required to exist.
+      if (!$source.length || !$target.length || !$suffix.length || !$wrapper.length) {
+        return;
+      }
+      // Skip processing upon a form validation error on the machine name.
+      if ($target.hasClass('error')) {
+        return;
+      }
+      // Hide wrapper element.
+      $wrapper.hide();
+      // Append the machine name to the source field.
+      if ($target.is(':disabled')) {
+        var machine = $target.val();
+      }
+      else {
+        var machine = self.transliterate($source.val(), options);
+      }
+      var $preview = $('<span class="machine-name-value">' + machine + '</span>');
+      $suffix.empty()
+        .append(' ').append('<span class="machine-name-label">' + options.label + ':</span>')
+        .append(' ').append($preview);
+
+      // Append a link to edit it, if it is editable. But only if
+      // - the machine name is empty.
+      // - the human-readable name and transliterated machine name are equal.
+      if (!$target.is(':disabled') && ($target.val() == '' || $target.val() == machine)) {
+        var $link = $('<span class="admin-link"><a href="#">' + Drupal.t('Edit') + '</a></span>')
+          .click(function () {
+            $wrapper.show();
+            $target.focus();
+            $suffix.hide();
+            $source.unbind('keyup.machineName');
+            return false;
+          });
+        $suffix.append(' ').append($link);
+
+        // Process machine name in realtime when typed characters change.
+        $source.bind('keyup.machineName', function () {
+          machine = self.transliterate($(this).val(), options);
+          // Set machine readable name to the user entered value.
+          if (machine != '_' && machine != '') {
+            $target.val(machine);
+            $preview.text(machine);
+            $suffix.show();
+          }
+          else {
+            $suffix.hide();
+            $target.val(machine);
+            $preview.empty();
+          }
+        });
+        // Call keyup event on source element.
+        $source.keyup();
+      }
+    });
+  },
+
+  /**
+   * Transliterate a human-readable name to a machine name.
+   *
+   * @param source
+   *   The to be transliterated source string.
+   * @param settings
+   *   The machine name settings for the corresponding field, containing:
+   *   - pattern: A regular expression (without modifiers) matching
+   *     disallowed characters in the machine readable name; e.g., '[^a-z0-9]+'.
+   *   - replace: A replacement string to replace disallowed characters;
+   *     e.g., '-' or '_'.
+   *
+   * @return
+   *   The transliterated source string.
+   */
+  transliterate: function (source, settings) {
+    var rx = new RegExp(settings.pattern, 'g');
+    return source.toLowerCase().replace(rx, settings.replace);
+  }
+};
+
+})(jQuery);
Index: modules/menu/menu.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v
retrieving revision 1.87
diff -u -p -r1.87 menu.admin.inc
--- modules/menu/menu.admin.inc	4 Oct 2010 18:00:46 -0000	1.87
+++ modules/menu/menu.admin.inc	5 Oct 2010 14:07:02 -0000
@@ -435,41 +435,26 @@ function menu_edit_menu($form, &$form_st
       '#title' => t('Title'),
       '#default_value' => $menu['title'],
       '#required' => TRUE,
-      '#field_suffix' => ' <small id="edit-title-suffix">&nbsp;</small>',
     );
   }
 
   // The internal menu name can only be defined during initial menu creation.
-  if (!empty($menu['old_name'])) {
-    $form['#insert'] = FALSE;
-    $form['menu_name'] = array('#type' => 'value', '#value' => $menu['menu_name']);
-  }
-  else {
-    $form['#insert'] = TRUE;
-    $js_settings = array(
-      'type' => 'setting',
-      'data' => array(
-        'machineReadableValue' => array(
-          'title' => array(
-            'text' => t('URL path'),
-            'target' => 'menu-name',
-            'searchPattern' => '[^a-z0-9]+',
-            'replaceToken' => '-',
-          ),
-        ),
-      ),
-    );
-    $form['menu_name'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Menu name'),
-      '#maxsize' => MENU_MAX_MENU_NAME_LENGTH_UI,
-      '#description' => t('This text will be used to construct the URL for the menu. The name must contain only lowercase letters, numbers and hyphens, and must be unique.'),
-      '#required' => TRUE,
-      '#attached' => array(
-        'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
-      ),
-    );
-  }
+  $form['#insert'] = empty($menu['old_name']);
+  $form['menu_name'] = array(
+    '#type' => 'machine_name',
+    '#title' => t('Menu name'),
+    '#default_value' => $menu['menu_name'],
+    '#maxlength' => MENU_MAX_MENU_NAME_LENGTH_UI,
+    '#description' => t('This text will be used to construct the URL for the menu. The name must contain only lowercase letters, numbers and hyphens, and must be unique.'),
+    '#machine_name' => array(
+      'exists' => 'menu_edit_menu_name_exists',
+      'source' => array('title'),
+      'label' => t('URL path'),
+      'pattern' => '[^a-z0-9-]+',
+      'replace' => '-',
+    ),
+    '#disabled' => !empty($menu['old_name']) || isset($system_menus[$menu['menu_name']]),
+  );
 
   $form['description'] = array(
     '#type' => 'textarea',
@@ -560,26 +545,18 @@ function menu_delete_menu_confirm_submit
 }
 
 /**
- * Validates the human and machine-readable names when adding or editing a menu.
- */
-function menu_edit_menu_validate($form, &$form_state) {
-  $item = $form_state['values'];
-  if (preg_match('/[^a-z0-9-]/', $item['menu_name'])) {
-    form_set_error('menu_name', t('The menu name may only consist of lowercase letters, numbers, and hyphens.'));
-  }
-  if ($form['#insert']) {
-    if (strlen($item['menu_name']) > MENU_MAX_MENU_NAME_LENGTH_UI) {
-      form_set_error('menu_name', format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."));
-    }
+ * Returns whether a menu name already exists.
+ *
+ * @see menu_edit_menu()
+ * @see form_validate_machine_name()
+ */
+function menu_edit_menu_name_exists($value) {
+  // 'menu-' is added to the menu name to avoid name-space conflicts.
+  $value = 'menu-' . $value;
+  $custom_exists = db_query_range('SELECT 1 FROM {menu_custom} WHERE menu_name = :menu', 0, 1, array(':menu' => $value))->fetchField();
+  $link_exists = db_query_range("SELECT 1 FROM {menu_links} WHERE menu_name = :menu", 0, 1, array(':menu' => $value))->fetchField();
 
-    // We will add 'menu-' to the menu name to help avoid name-space conflicts.
-    $item['menu_name'] = 'menu-' . $item['menu_name'];
-    $custom_exists = db_query_range('SELECT 1 FROM {menu_custom} WHERE menu_name = :menu', 0, 1, array(':menu' => $item['menu_name']))->fetchField();
-    $link_exists = db_query_range("SELECT 1 FROM {menu_links} WHERE menu_name = :menu", 0, 1, array(':menu' => $item['menu_name']))->fetchField();
-    if ($custom_exists || $link_exists) {
-      form_set_error('menu_name', t('The menu already exists.'));
-    }
-  }
+  return $custom_exists || $link_exists;
 }
 
 /**
Index: modules/menu/menu.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.test,v
retrieving revision 1.41
diff -u -p -r1.41 menu.test
--- modules/menu/menu.test	24 Sep 2010 00:37:43 -0000	1.41
+++ modules/menu/menu.test	5 Oct 2010 14:07:02 -0000
@@ -140,7 +140,11 @@ class MenuTestCase extends DrupalWebTest
     $this->drupalPost('admin/structure/menu/add', $edit, t('Save'));
 
     // Verify that using a menu_name that is too long results in a validation message.
-    $this->assertText(format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."), t('Validation failed when menu name is too long.'));
+    $this->assertRaw(t('!name cannot be longer than %max characters but is currently %length characters long.', array(
+      '!name' => t('Menu name'),
+      '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
+      '%length' => drupal_strlen($menu_name),
+    )));
 
     // Change the menu_name so it no longer exceeds the maximum length.
     $menu_name = substr(hash('sha256', $this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI);
@@ -148,7 +152,11 @@ class MenuTestCase extends DrupalWebTest
     $this->drupalPost('admin/structure/menu/add', $edit, t('Save'));
 
     // Verify that no validation error is given for menu_name length.
-    $this->assertNoText(format_plural(MENU_MAX_MENU_NAME_LENGTH_UI, "The menu name can't be longer than 1 character.", "The menu name can't be longer than @count characters."), t('Validation failed when menu name is too long.'));
+    $this->assertNoRaw(t('!name cannot be longer than %max characters but is currently %length characters long.', array(
+      '!name' => t('Menu name'),
+      '%max' => MENU_MAX_MENU_NAME_LENGTH_UI,
+      '%length' => drupal_strlen($menu_name),
+    )));
     // Unlike most other modules, there is no confirmation message displayed.
 
     $this->drupalGet('admin/structure/menu');
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.117
diff -u -p -r1.117 content_types.inc
--- modules/node/content_types.inc	3 Sep 2010 17:47:20 -0000	1.117
+++ modules/node/content_types.inc	5 Oct 2010 14:07:02 -0000
@@ -94,41 +94,18 @@ function node_type_form($form, &$form_st
     '#description' => t('The human-readable name of this content type. This text will be displayed as part of the list on the <em>Add new content</em> page. It is recommended that this name begin with a capital letter and contain only letters, numbers, and spaces. This name must be unique.'),
     '#required' => TRUE,
     '#size' => 30,
-    '#field_suffix' => ' <small id="edit-name-suffix">' . ($type->locked ? t('Machine name: @name', array('@name' => $type->type)) : '&nbsp;') . '</small>',
   );
 
-  if (!$type->locked) {
-    $js_settings = array(
-      'type' => 'setting',
-      'data' => array(
-        'machineReadableValue' => array(
-          'name' => array(
-            'text' => t('Machine name'),
-            'target' => 'type',
-            'searchPattern' => '[^a-z0-9]+',
-            'replaceToken' => '_',
-          ),
-        ),
-      ),
-    );
-    $form['type'] = array(
-      '#title' => t('Machine name'),
-      '#type' => 'textfield',
-      '#default_value' => $type->type,
-      '#maxlength' => 32,
-      '#required' => TRUE,
-      '#description' => t('The machine-readable name of this content type. This text will be used for constructing the URL of the <em>add new content</em> page for this content type. This name must contain only lowercase letters, numbers, and underscores. Underscores will be converted into hyphens when constructing the URL of the <em>add new content</em> page. This name must be unique.'),
-      '#attached' => array(
-        'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
-      ),
-    );
-  }
-  else {
-    $form['type'] = array(
-      '#type' => 'value',
-      '#value' => $type->type,
-    );
-  }
+  $form['type'] = array(
+    '#type' => 'machine_name',
+    '#default_value' => $type->type,
+    '#maxlength' => 32,
+    '#disabled' => $type->locked,
+    '#machine_name' => array(
+      'exists' => 'node_type_load',
+    ),
+    '#description' => t('The machine-readable name of this content type. This text will be used for constructing the URL of the <em>add new content</em> page for this content type. This name must contain only lowercase letters, numbers, and underscores. Underscores will be converted into hyphens when constructing the URL of the <em>add new content</em> page. This name must be unique.'),
+  );
 
   $form['description'] = array(
     '#title' => t('Description'),
@@ -276,12 +253,6 @@ function node_type_form_validate($form, 
   $types = node_type_get_names();
 
   if (!$form_state['values']['locked']) {
-    if (isset($types[$type->type]) && $type->type != $old_type) {
-      form_set_error('type', t('The machine-readable name %type is already taken.', array('%type' => $type->type)));
-    }
-    if (!preg_match('!^[a-z0-9_]+$!', $type->type)) {
-      form_set_error('type', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
-    }
     // 'theme' conflicts with theme_node_form().
     // '0' is invalid, since elsewhere we check it using empty().
     if (in_array($type->type, array('0', 'theme'))) {
Index: modules/system/system.admin.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.css,v
retrieving revision 1.2
diff -u -p -r1.2 system.admin.css
--- modules/system/system.admin.css	25 Sep 2010 02:28:14 -0000	1.2
+++ modules/system/system.admin.css	5 Oct 2010 14:07:02 -0000
@@ -46,6 +46,16 @@ div.admin .expert-link {
 }
 
 /**
+ * Quick inline admin links.
+ */
+small .admin-link:before {
+  content: '[';
+}
+small .admin-link:after {
+  content: ']';
+}
+
+/**
  * Modules page.
  */
 #system-modules div.incompatible {
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.315
diff -u -p -r1.315 system.admin.inc
--- modules/system/system.admin.inc	5 Oct 2010 00:31:18 -0000	1.315
+++ modules/system/system.admin.inc	5 Oct 2010 14:07:02 -0000
@@ -2069,28 +2069,12 @@ function system_add_date_format_type_for
     '#title' => t('Date type'),
     '#type' => 'textfield',
     '#required' => TRUE,
-    '#field_suffix' => ' <small id="edit-date-type-suffix">&nbsp;</small>',
-  );
-  $js_settings = array(
-    'type' => 'setting',
-    'data' => array(
-      'machineReadableValue' => array(
-        'date-type' => array(
-          'text' => t('Machine name'),
-          'target' => 'machine-name',
-          'searchPattern' => '[^a-z0-9]+',
-          'replaceToken' => '_',
-        ),
-      ),
-    ),
   );
   $form['machine_name'] = array(
-    '#title' => t('Machine readable name'),
-    '#description' => t('The unique machine readable name for this date type, can only contain lowercase letters, numbers and underscores.'),
-    '#type' => 'textfield',
-    '#required' => TRUE,
-    '#attached' => array(
-      'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
+    '#type' => 'machine_name',
+    '#machine_name' => array(
+      'exists' => 'system_get_date_types',
+      'source' => array('date_type'),
     ),
   );
 
Index: modules/system/system.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.js,v
retrieving revision 1.40
diff -u -p -r1.40 system.js
--- modules/system/system.js	30 Jan 2010 00:29:10 -0000	1.40
+++ modules/system/system.js	5 Oct 2010 14:07:02 -0000
@@ -148,78 +148,4 @@ Drupal.behaviors.pageCache = {
   }
 };
 
-/**
- * Attach the auto machine readable name behavior.
- *
- * Settings are expected to be an object of elements to process, where the key
- * defines the source element in the form and the value is an object defining
- * the following properties:
- * - text: The label to display before the auto-generated value.
- * - target: The target form element name.
- * - searchPattern: A regular expression (without modifiers) matching disallowed
- *   characters in the machine readable name, f.e. '[^a-z0-9]+'.
- * - replaceToken: A replacement string to replace disallowed characters, f.e.
- *   '-' or '_'.
- *
- * @see menu_edit_menu()
- */
-Drupal.behaviors.machineReadableValue = {
-  attach: function () {
-    var self = this;
-
-    for (var value in Drupal.settings.machineReadableValue) {
-      var settings = Drupal.settings.machineReadableValue[value];
-
-      // Build selector for the source name entered by a user.
-      var source = '#edit-' + value;
-      var suffix = source + '-suffix';
-      // Build selector for the machine readable name.
-      var target = '#edit-' + settings.target;
-      // Build selector for the wrapper element around the target field.
-      var wrapper = '.form-item-' + settings.target;
-
-      // Do not process the element if we got an error or the given name and the
-      // machine readable name are identical or the machine readable name is
-      // empty.
-      if (!$(target).hasClass('error') && ($(target).val() == '' || $(target).val() == self.transliterate($(source).val(), settings))) {
-        // Hide wrapper element.
-        $(wrapper).hide();
-        // Bind keyup event to source element.
-        $(source).keyup(function () {
-          var machine = self.transliterate($(this).val(), settings);
-          if (machine != '_' && machine != '') {
-            // Set machine readable name to the user entered value.
-            $(target).val(machine);
-            // Append the machine readable name and a link to edit it to the source field.
-            $(suffix).empty().append(' ' + settings.text + ': ' + machine + ' [').append($('<a href="#">' + Drupal.t('Edit') + '</a>').click(function () {
-              $(wrapper).show();
-              $(target).focus();
-              $(suffix).hide();
-              $(source).unbind('keyup');
-              return false;
-            })).append(']');
-          }
-          else {
-            $(target).val(machine);
-            $(suffix).text('');
-          }
-        });
-        // Call keyup event on source element.
-        $(source).keyup();
-      }
-    }
-  },
-
-  /**
-   * Transliterate a human-readable name to a machine name.
-   *
-   * The result should not contain any character matching settings.searchPattern,
-   * invalid characters are typically replaced with settings.replaceToken.
-   */
-  transliterate: function (source, settings) {
-    var searchPattern = new RegExp(settings.searchPattern, 'g');
-    return source.toLowerCase().replace(searchPattern, settings.replaceToken);
-  }
-};
-
 })(jQuery);
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.975
diff -u -p -r1.975 system.module
--- modules/system/system.module	5 Oct 2010 06:23:18 -0000	1.975
+++ modules/system/system.module	5 Oct 2010 14:07:02 -0000
@@ -347,6 +347,18 @@ function system_element_info() {
     '#theme' => 'textfield',
     '#theme_wrappers' => array('form_element'),
   );
+  $types['machine_name'] = array(
+    '#input' => TRUE,
+    '#default_value' => NULL,
+    '#required' => TRUE,
+    '#maxlength' => 64,
+    '#size' => 60,
+    '#autocomplete_path' => FALSE,
+    '#process' => array('form_process_machine_name', 'ajax_process_form'),
+    '#element_validate' => array('form_validate_machine_name'),
+    '#theme' => 'textfield',
+    '#theme_wrappers' => array('form_element'),
+  );
   $types['password'] = array(
     '#input' => TRUE,
     '#size' => 60,
Index: modules/system/system.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.test,v
retrieving revision 1.146
diff -u -p -r1.146 system.test
--- modules/system/system.test	5 Oct 2010 00:22:24 -0000	1.146
+++ modules/system/system.test	5 Oct 2010 14:07:02 -0000
@@ -948,7 +948,7 @@ class DateTimeFunctionalTest extends Dru
 
     // Add custom date type.
     $this->clickLink(t('Add date type'));
-    $date_type = $this->randomName(8);
+    $date_type = strtolower($this->randomName(8));
     $machine_name = 'machine_' . $date_type;
     $date_format = 'd.m.Y - H:i';
     $edit = array(
Index: modules/taxonomy/taxonomy.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v
retrieving revision 1.110
diff -u -p -r1.110 taxonomy.admin.inc
--- modules/taxonomy/taxonomy.admin.inc	28 Sep 2010 03:30:37 -0000	1.110
+++ modules/taxonomy/taxonomy.admin.inc	5 Oct 2010 14:07:02 -0000
@@ -137,30 +137,13 @@ function taxonomy_form_vocabulary($form,
     '#default_value' => $vocabulary->name,
     '#maxlength' => 255,
     '#required' => TRUE,
-    '#field_suffix' => ' <small id="edit-name-suffix">&nbsp;</small>',
-  );
-  $js_settings = array(
-    'type' => 'setting',
-    'data' => array(
-      'machineReadableValue' => array(
-        'name' => array(
-          'text' => t('Machine name'),
-          'target' => 'machine-name',
-          'searchPattern' => '[^a-z0-9]+',
-          'replaceToken' => '_',
-        ),
-      ),
-    ),
   );
   $form['machine_name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Machine-readable name'),
+    '#type' => 'machine_name',
     '#default_value' => $vocabulary->machine_name,
     '#maxlength' => 255,
-    '#description' => t('The unique machine-readable name for this vocabulary, used for theme templates. Can only contain lowercase letters, numbers, and underscores.'),
-    '#required' => TRUE,
-    '#attached' => array(
-      'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
+    '#machine_name' => array(
+      'exists' => 'taxonomy_vocabulary_machine_name_load',
     ),
   );
   $form['description'] = array(
@@ -186,34 +169,6 @@ function taxonomy_form_vocabulary($form,
 }
 
 /**
- * Validation handler for the vocabulary form.
- *
- * @see taxonomy_form_vocabulary()
- */
-function taxonomy_form_vocabulary_validate($form, &$form_state) {
-  if ($form_state['clicked_button']['#value'] != t('Delete') && isset($form_state['values']['machine_name'])) {
-
-    // Restrict machine names to appropriate characters.
-    $machine_name = $form_state['values']['machine_name'];
-    if (!preg_match('!^[a-z0-9_]+$!', $form_state['values']['machine_name'])) {
-      form_set_error('machine_name', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
-    }
-    // Restrict machine names to 21 characters to avoid exceeding the limit
-    // for field names.
-    if (drupal_strlen($machine_name) > 21) {
-      form_set_error('machine_name', t('The machine-readable name must not exceed 21 characters.'));
-    }
-
-    // Do not allow duplicate machine names.
-    $vocabularies = taxonomy_get_vocabularies();
-    foreach ($vocabularies as $vocabulary) {
-      if ($machine_name == $vocabulary->machine_name && (!isset($form_state['values']['vid']) || $vocabulary->vid != $form_state['values']['vid'])) {
-        form_set_error('machine_name', t('This machine-readable name is already in use by another vocabulary and must be unique.'));
-      }
-    }
-  }
-}
-/**
  * Accept the form submission for a vocabulary and save the results.
  */
 function taxonomy_form_vocabulary_submit($form, &$form_state) {
Index: modules/taxonomy/taxonomy.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v
retrieving revision 1.93
diff -u -p -r1.93 taxonomy.test
--- modules/taxonomy/taxonomy.test	1 Oct 2010 01:37:13 -0000	1.93
+++ modules/taxonomy/taxonomy.test	5 Oct 2010 14:07:02 -0000
@@ -92,7 +92,7 @@ class TaxonomyVocabularyFunctionalTest e
     // Try to submit a vocabulary with a duplicate machine name.
     $edit['machine_name'] = $machine_name;
     $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
-    $this->assertText(t('This machine-readable name is already in use by another vocabulary and must be unique.'), t('Duplicate machine name validation was successful'));
+    $this->assertText(t('This machine-readable name is already in use. It must be unique.'), t('Duplicate machine name validation was successful'));
 
     // Try to submit an invalid machine name.
     $edit['machine_name'] = '!&^%';
