diff --git includes/form.inc includes/form.inc
index 9c596b0..8f13f44 100644
--- includes/form.inc
+++ includes/form.inc
@@ -3053,6 +3053,8 @@ function form_process_tableselect($element) {
  *     - 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.
+ *     - error: (optional) A custom form error message string to show, if the
+ *       machine name contains disallowed characters.
  *   - #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
@@ -3119,24 +3121,38 @@ function form_process_machine_name($element, &$form_state) {
 
 /**
  * Form element validation handler for #type 'machine_name'.
+ *
+ * Note that #maxlength is validated by _form_validate() already.
  */
 function form_validate_machine_name(&$element, &$form_state) {
-  // Restrict machine names to appropriate characters.
+  // Verify that the machine name not only consists of replacement tokens.
+  if (preg_match('@^' . $element['#machine_name']['replace'] . '+$@', $element['#value'])) {
+    form_error($element, t('The machine-readable name must contain unique characters.'));
+  }
+
+  // Verify that the machine name matches the valid pattern.
   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.'));
+      // Since a hyphen is the most common alternative replacement character, a
+      // corresponding validation error message is supported here.
+      if ($element['#machine_name']['replace'] == '-') {
+        form_error($element, t('The machine-readable name must contain only lowercase letters, numbers, and hyphens.'));
+      }
+      // Otherwise, we assume the default (an underscore).
+      else {
+        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.'));
+      form_error($element, t('The machine-readable name is already in use. It must be unique.'));
     }
   }
 }
diff --git modules/menu/menu.admin.inc modules/menu/menu.admin.inc
index 03af27e..c99c4bf 100644
--- modules/menu/menu.admin.inc
+++ modules/menu/menu.admin.inc
@@ -445,7 +445,7 @@ function menu_edit_menu($form, &$form_state, $type, $menu = array()) {
     '#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.'),
+    '#description' => t('A unique name to construct the URL for the menu. It must only contain lowercase letters, numbers and hyphens.'),
     '#machine_name' => array(
       'exists' => 'menu_edit_menu_name_exists',
       'source' => array('title'),
diff --git modules/node/content_types.inc modules/node/content_types.inc
index 2bf1131..ae59811 100644
--- modules/node/content_types.inc
+++ modules/node/content_types.inc
@@ -104,7 +104,9 @@ function node_type_form($form, &$form_state, $type = NULL) {
     '#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.'),
+    '#description' => t('A unique machine-readable name for this content type. It must only contain lowercase letters, numbers, and underscores. This name will be used for constructing the URL of the %node-add page, in which underscores will be converted into hyphens.', array(
+      '%node-add' => t('Add new content'),
+    )),
   );
 
   $form['description'] = array(
diff --git modules/taxonomy/taxonomy.test modules/taxonomy/taxonomy.test
index cbbf41e..c16ec0b 100644
--- modules/taxonomy/taxonomy.test
+++ modules/taxonomy/taxonomy.test
@@ -92,7 +92,7 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
     // 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. It must be unique.'), t('Duplicate machine name validation was successful'));
+    $this->assertText(t('The machine-readable name is already in use. It must be unique.'));
 
     // Try to submit an invalid machine name.
     $edit['machine_name'] = '!&^%';
