? drupal_menu_paths.patch
? misc/sample.png
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.328
diff -u -p -r1.328 menu.inc
--- includes/menu.inc	10 Jun 2009 21:52:36 -0000	1.328
+++ includes/menu.inc	2 Jul 2009 19:40:09 -0000
@@ -2721,6 +2721,51 @@ function _menu_router_save($menu, $masks
 }
 
 /**
+ * Check if a word is not reserved within a given path.
+ *
+ * @param $path
+ *   The path in which to check reserved words.
+ * @param $word
+ *   The word to check within the given path.
+ * @return
+ *   Returns TRUE if the word is reserved, FALSE otherwise.
+ */
+function menu_path_is_reserved($path, $word) {
+  return in_array($word, menu_path_reserved_words($path));
+}
+
+/**
+ * Retrieves a list of words that are in-use by existing modules at a menu path.
+ *
+ * @param $path
+ *   The path that should be checked for reserved words. For example, if
+ *   checking for the safety of "node/types/type-name", pass in the path
+ *   "node/types". The wildcard "%" may be used for parts of the path that are
+ *   dynamic.
+ * @return
+ *   An array of words that are reserved at the given path.
+ */
+function menu_path_reserved_words($path) {
+  $router = menu_router_build();
+  $path_parts = explode('/', $path);
+  $reserved = array();
+  $check_part = '';
+  foreach ($router[0] as $router_item) {
+    foreach ($path_parts as $index => $key) {
+      $check_part = &$router_item['_parts'][$index];
+      if ($check_part != $key && $key != '%') {
+        continue 2;
+      }
+    }
+    $check_part = &$router_item['_parts'][$index + 1];
+    if (!empty($check_part) && !isset($reserved[$check_part]) && $check_part != '%') {
+      $reserved[$check_part] = $check_part;
+    }
+  }
+  return $reserved;
+}
+
+/**
  * Returns TRUE if a path is external (e.g. http://example.com).
  */
 function menu_path_is_external($path) {
Index: modules/contact/contact.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.module,v
retrieving revision 1.117
diff -u -p -r1.117 contact.module
--- modules/contact/contact.module	13 Jun 2009 20:40:07 -0000	1.117
+++ modules/contact/contact.module	2 Jul 2009 19:40:09 -0000
@@ -27,7 +27,7 @@ function contact_help($path, $arg) {
       else {
         $menu_note = '';
       }
-      $output .= '<p>' . t('The contact module also adds a <a href="@menu-settings">menu item</a> (disabled by default) to the navigation block.', array('@menu-settings' => url('admin/build/menu'))) . ' ' . $menu_note . '</p>';
+      $output .= '<p>' . t('The contact module also adds a <a href="@menu-settings">menu item</a> (disabled by default) to the navigation block.', array('@menu-settings' => url('admin/build/menus'))) . ' ' . $menu_note . '</p>';
       return $output;
   }
 }
Index: modules/forum/forum.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.test,v
retrieving revision 1.23
diff -u -p -r1.23 forum.test
--- modules/forum/forum.test	27 Jun 2009 19:49:07 -0000	1.23
+++ modules/forum/forum.test	2 Jul 2009 19:40:09 -0000
@@ -93,7 +93,7 @@ class ForumTestCase extends DrupalWebTes
 
     // Add forum to navigation menu.
     $edit = array();
-    $this->drupalPost('admin/build/menu-customize/navigation', $edit, t('Save configuration'));
+    $this->drupalPost('admin/build/menus/navigation', $edit, t('Save configuration'));
     $this->assertResponse(200);
 
     // Edit forum taxonomy.
Index: modules/locale/locale.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v
retrieving revision 1.28
diff -u -p -r1.28 locale.test
--- modules/locale/locale.test	30 Jun 2009 18:21:06 -0000	1.28
+++ modules/locale/locale.test	2 Jul 2009 19:40:09 -0000
@@ -1365,12 +1365,12 @@ class LocaleContentFunctionalTest extend
     $this->drupalPost('admin/international/language/configure', $edit, t('Save settings'));
 
     // Set page content type to use multilingual support.
-    $this->drupalGet('admin/build/node-type/page');
+    $this->drupalGet('admin/build/types/page');
     $this->assertText(t('Multilingual support'), t('Multilingual support fieldset present on content type configuration form.'));
     $edit = array(
       'language_content_type' => 1,
     );
-    $this->drupalPost('admin/build/node-type/page', $edit, t('Save content type'));
+    $this->drupalPost('admin/build/types/page', $edit, t('Save content type'));
     $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Page')), t('Page content type has been updated.'));
     $this->drupalLogout();
 
Index: modules/menu/menu.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v
retrieving revision 1.52
diff -u -p -r1.52 menu.admin.inc
--- modules/menu/menu.admin.inc	29 Jun 2009 14:24:56 -0000	1.52
+++ modules/menu/menu.admin.inc	2 Jul 2009 19:40:09 -0000
@@ -15,9 +15,9 @@ function menu_overview_page() {
   $rows = array();
   foreach ($result as $menu) {
     $row = array(theme('menu_admin_overview', $menu['title'], $menu['menu_name'], $menu['description']));
-    $row[] = array('data' => l(t('list links'), 'admin/build/menu-customize/' . $menu['menu_name']));
-    $row[] = array('data' => l(t('edit menu'), 'admin/build/menu-customize/' . $menu['menu_name'] . '/edit'));
-    $row[] = array('data' => l(t('add link'), 'admin/build/menu-customize/' . $menu['menu_name'] . '/add'));
+    $row[] = array('data' => l(t('list links'), 'admin/build/menus/' . $menu['menu_name']));
+    $row[] = array('data' => l(t('edit menu'), 'admin/build/menus/' . $menu['menu_name'] . '/edit'));
+    $row[] = array('data' => l(t('add link'), 'admin/build/menus/' . $menu['menu_name'] . '/add'));
     $rows[] = $row;
   }
 
@@ -65,7 +65,7 @@ function menu_overview_form(&$form_state
     );
   }
   else {
-    $form['#empty_text'] = t('There are no menu links yet. <a href="@link">Add link</a>.', array('@link' => url('admin/build/menu-customize/'. $form['#menu']['menu_name'] .'/add')));
+    $form['#empty_text'] = t('There are no menu links yet. <a href="@link">Add link</a>.', array('@link' => url('admin/build/menus/'. $form['#menu']['menu_name'] .'/add')));
   }
   return $form;
 }
@@ -108,14 +108,14 @@ function _menu_overview_tree_form($tree)
       );
       // Build a list of operations.
       $operations = array();
-      $operations['edit'] = l(t('edit'), 'admin/build/menu/item/' . $item['mlid'] . '/edit');
+      $operations['edit'] = l(t('edit'), 'admin/build/menus/' . $item['menu_name'] . '/' . $item['mlid']);
       // Only items created by the menu module can be deleted.
       if ($item['module'] == 'menu' || $item['updated'] == 1) {
-        $operations['delete'] = l(t('delete'), 'admin/build/menu/item/' . $item['mlid'] . '/delete');
+        $operations['delete'] = l(t('delete'), 'admin/build/menus/' . $item['menu_name'] . '/' . $item['mlid'] . '/delete');
       }
       // Set the reset column.
       elseif ($item['module'] == 'system' && $item['customized']) {
-        $operations['reset'] = l(t('reset'), 'admin/build/menu/item/' . $item['mlid'] . '/reset');
+        $operations['reset'] = l(t('reset'), 'admin/build/menus/' . $item['menu_name'] . '/' . $item['mlid'] . '/reset');
       }
 
       $form[$mlid]['operations'] = array();
@@ -260,7 +260,7 @@ function menu_edit_item(&$form_state, $t
     '#description' => t('The text to be used for this link in the menu.'),
     '#required' => TRUE,
   );
-  foreach (array('link_path', 'mlid', 'module', 'has_children', 'options') as $key) {
+  foreach (array('menu_name', 'link_path', 'mlid', 'module', 'has_children', 'options') as $key) {
     $form['menu'][$key] = array('#type' => 'value', '#value' => $item[$key]);
   }
   // Any item created or edited via this interface is considered "customized".
@@ -375,7 +375,7 @@ function menu_edit_item_validate($form, 
  * Submit function for the delete button on the menu item editing form.
  */
 function menu_item_delete_submit($form, &$form_state) {
-  $form_state['redirect'] = 'admin/build/menu/item/' . $form_state['values']['menu']['mlid'] . '/delete';
+  $form_state['redirect'] = 'admin/build/menus/' . $form_state['values']['menu']['menu_name'] . '/' . $form_state['values']['menu']['mlid'] . '/delete';
 }
 
 /**
@@ -394,7 +394,7 @@ function menu_edit_item_submit($form, &$
   if (!menu_link_save($item)) {
     drupal_set_message(t('There was an error saving the menu link.'), 'error');
   }
-  $form_state['redirect'] = 'admin/build/menu-customize/' . $item['menu_name'];
+  $form_state['redirect'] = 'admin/build/menus/' . $item['menu_name'];
 }
 
 /**
@@ -456,7 +456,7 @@ function menu_edit_menu(&$form_state, $t
  * Submit function for the 'Delete' button on the menu editing form.
  */
 function menu_custom_delete_submit($form, &$form_state) {
-  $form_state['redirect'] = 'admin/build/menu-customize/' . $form_state['values']['menu_name'] . '/delete';
+  $form_state['redirect'] = 'admin/build/menus/' . $form_state['values']['menu_name'] . '/delete';
 }
 
 /**
@@ -483,7 +483,7 @@ function menu_delete_menu_confirm(&$form
     $caption .= '<p>' . format_plural($num_links, '<strong>Warning:</strong> There is currently 1 menu link in %title. It will be deleted (system-defined items will be reset).', '<strong>Warning:</strong> There are currently @count menu links in %title. They will be deleted (system-defined links will be reset).', array('%title' => $menu['title'])) . '</p>';
   }
   $caption .= '<p>' . t('This action cannot be undone.') . '</p>';
-  return confirm_form($form, t('Are you sure you want to delete the custom menu %title?', array('%title' => $menu['title'])), 'admin/build/menu-customize/' . $menu['menu_name'], $caption, t('Delete'));
+  return confirm_form($form, t('Are you sure you want to delete the custom menu %title?', array('%title' => $menu['title'])), 'admin/build/menus/' . $menu['menu_name'], $caption, t('Delete'));
 }
 
 /**
@@ -491,7 +491,7 @@ function menu_delete_menu_confirm(&$form
  */
 function menu_delete_menu_confirm_submit($form, &$form_state) {
   $menu = $form['#menu'];
-  $form_state['redirect'] = 'admin/build/menu';
+  $form_state['redirect'] = 'admin/build/menus';
   // System-defined menus may not be deleted - only menus defined by this module.
   $system_menus = menu_list_system_menus();
   if (isset($system_menus[$menu['menu_name']])  || !(db_query("SELECT 1 FROM {menu_custom} WHERE menu_name = :menu", array(':menu' => $menu['menu_name']))->fetchField())) {
@@ -503,7 +503,7 @@ function menu_delete_menu_confirm_submit
     menu_reset_item($item);
   }
   // Delete all links to the overview page for this menu.
-  $result = db_query("SELECT mlid FROM {menu_links} ml WHERE ml.link_path = :link", array(':link' => 'admin/build/menu-customize/' . $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC));
+  $result = db_query("SELECT mlid FROM {menu_links} ml WHERE ml.link_path = :link", array(':link' => 'admin/build/menus/' . $menu['menu_name']), array('fetch' => PDO::FETCH_ASSOC));
   foreach ($result as $m) {
     menu_link_delete($m['mlid']);
   }
@@ -544,7 +544,9 @@ function menu_edit_menu_validate($form, 
     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."));
     }
-
+    if (menu_path_is_reserved('admin/build/menus', 'menu-' . $item['menu_name'])) {
+      form_set_error('menu_name', t('The menu name %name cannot be used because it is a reserved word.', array('%name' => $item['menu_name'])));
+    }
     // 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('SELECT menu_name FROM {menu_custom} WHERE menu_name = :menu', array(':menu' => $item['menu_name']))->fetchField();
@@ -560,7 +562,7 @@ function menu_edit_menu_validate($form, 
  */
 function menu_edit_menu_submit($form, &$form_state) {
   $menu = $form_state['values'];
-  $path = 'admin/build/menu-customize/';
+  $path = 'admin/build/menus/';
   if ($form['#insert']) {
     // Add 'menu-' to the menu name to help avoid name-space conflicts.
     $menu['menu_name'] = 'menu-' . $menu['menu_name'];
@@ -569,7 +571,7 @@ function menu_edit_menu_submit($form, &$
     $link['router_path'] = $path . '%';
     $link['module'] = 'menu';
     $link['plid'] = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :link AND module = :module", array(
-      ':link' => 'admin/build/menu',
+      ':link' => 'admin/build/menus',
       ':module' => 'system'
     ))
     ->fetchField();
@@ -619,7 +621,7 @@ function menu_item_delete_page($item) {
  */
 function menu_item_delete_form(&$form_state, $item) {
   $form['#item'] = $item;
-  return confirm_form($form, t('Are you sure you want to delete the custom menu link %item?', array('%item' => $item['link_title'])), 'admin/build/menu-customize/' . $item['menu_name']);
+  return confirm_form($form, t('Are you sure you want to delete the custom menu link %item?', array('%item' => $item['link_title'])), 'admin/build/menus/' . $item['menu_name']);
 }
 
 /**
@@ -631,7 +633,7 @@ function menu_item_delete_form_submit($f
   $t_args = array('%title' => $item['link_title']);
   drupal_set_message(t('The menu link %title has been deleted.', $t_args));
   watchdog('menu', 'Deleted menu link %title.', $t_args, WATCHDOG_NOTICE);
-  $form_state['redirect'] = 'admin/build/menu-customize/' . $item['menu_name'];
+  $form_state['redirect'] = 'admin/build/menus/' . $item['menu_name'];
 }
 
 /**
@@ -639,7 +641,7 @@ function menu_item_delete_form_submit($f
  */
 function menu_reset_item_confirm(&$form_state, $item) {
   $form['item'] = array('#type' => 'value', '#value' => $item);
-  return confirm_form($form, t('Are you sure you want to reset the link %item to its default values?', array('%item' => $item['link_title'])), 'admin/build/menu-customize/' . $item['menu_name'], t('Any customizations will be lost. This action cannot be undone.'), t('Reset'));
+  return confirm_form($form, t('Are you sure you want to reset the link %item to its default values?', array('%item' => $item['link_title'])), 'admin/build/menus/' . $item['menu_name'], t('Any customizations will be lost. This action cannot be undone.'), t('Reset'));
 }
 
 /**
@@ -649,7 +651,7 @@ function menu_reset_item_confirm_submit(
   $item = $form_state['values']['item'];
   $new_item = menu_reset_item($item);
   drupal_set_message(t('The menu link was reset to its default settings.'));
-  $form_state['redirect'] = 'admin/build/menu-customize/' . $new_item['menu_name'];
+  $form_state['redirect'] = 'admin/build/menus/' . $new_item['menu_name'];
 }
 
 /**
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.193
diff -u -p -r1.193 menu.module
--- modules/menu/menu.module	28 Jun 2009 13:08:15 -0000	1.193
+++ modules/menu/menu.module	2 Jul 2009 19:40:10 -0000
@@ -19,15 +19,15 @@ function menu_help($path, $arg) {
   switch ($path) {
     case 'admin/help#menu':
       $output = '<p>' . t("The menu module provides an interface to control and customize Drupal's powerful menu system. Menus are a hierarchical collection of links used to navigate a website.  Each menu is rendered in a block that may be positioned and displayed using Drupal's flexible block system. Five menus are provided by Drupal and are always present: <em>Navigation</em>, <em>Management</em>, <em>User menu</em>, <em>Main menu</em>, and <em>Secondary menu</em>. The <em>Management</em> menu contains links for administration and content creation, while the <em>Navigation</em> menu is the default location for site navigation links created by newly enabled modules. Both of these are often displayed in either the left or right sidebar. Most Drupal themes also provide support for the <em>Main links</em> and <em>Secondary links</em>, by displaying them in either the header or footer of each page. The <em>Main menu</em> is the default source for the <em>Main links</em> and the <em>User menu</em> is the default source for the <em>Secondary links</em>.  By default, the <em>User menu</em> has links to take the current user to their account or allow them to log out, while the <em>Main menu</em> and <em>Secondary menu</em> contain no menu links but may be configured to contain custom menu items specific to your site. You may create an unlimited number of additional menus, each of which will automatically have an associated block.") . '</p>';
-      $output .= '<p>' . t('The <a href="@menu">menus page</a> displays all menus currently available on your site. Select a menu from this list to add or edit a menu link, or to rearrange links within the menu. Create new menus using the <a href="@add-menu">add menu page</a> (the block containing a new menu must also be enabled on the <a href="@blocks">blocks administration page</a>).', array('@menu' => url('admin/build/menu'), '@add-menu' => url('admin/build/menu/add'), '@blocks' => url('admin/build/block'))) . '</p>';
+      $output .= '<p>' . t('The <a href="@menu">menus page</a> displays all menus currently available on your site. Select a menu from this list to add or edit a menu link, or to rearrange links within the menu. Create new menus using the <a href="@add-menu">add menu page</a> (the block containing a new menu must also be enabled on the <a href="@blocks">blocks administration page</a>).', array('@menu' => url('admin/build/menus'), '@add-menu' => url('admin/build/menus/add'), '@blocks' => url('admin/build/block'))) . '</p>';
       $output .= '<p>' . t('For more information, see the online handbook entry for <a href="@menu">Menu module</a>.', array('@menu' => 'http://drupal.org/handbook/modules/menu/')) . '</p>';
       return $output;
-    case 'admin/build/menu/add':
+    case 'admin/build/menus/add':
       return '<p>' . t('Enter the name for your new menu. Remember to enable the newly created block in the <a href="@blocks">blocks administration page</a>.', array('@blocks' => url('admin/build/block'))) . '</p>';
-    case 'admin/build/menu/item/add':
+    case 'admin/build/menus/%/add':
       return '<p>' . t('Enter the title and path for your new menu link.') . '</p>';
   }
-  if ($path == 'admin/build/menu' && module_exists('block')) {
+  if ($path == 'admin/build/menus' && module_exists('block')) {
     return '<p>' . t('Each menu has a corresponding block that is managed on the <a href="@blocks">blocks administration page</a>.', array('@blocks' => url('admin/build/block'))) . '</p>';
   }
 }
@@ -48,26 +48,26 @@ function menu_perm() {
  * Implement hook_menu().
  */
 function menu_menu() {
-  $items['admin/build/menu'] = array(
+  $items['admin/build/menus'] = array(
     'title' => 'Menus',
     'description' => 'Add new menus to your site, edit existing menus, and rename and reorganize menu links.',
     'page callback' => 'menu_overview_page',
     'access callback' => 'user_access',
     'access arguments' => array('administer menu'),
   );
-  $items['admin/build/menu/list'] = array(
+  $items['admin/build/menus/list'] = array(
     'title' => 'List menus',
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
-  $items['admin/build/menu/add'] = array(
+  $items['admin/build/menus/add'] = array(
     'title' => 'Add menu',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_edit_menu', 'add'),
     'access arguments' => array('administer menu'),
     'type' => MENU_LOCAL_TASK,
   );
-  $items['admin/build/menu/settings'] = array(
+  $items['admin/build/menus/settings'] = array(
     'title' => 'Settings',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_configure'),
@@ -75,7 +75,7 @@ function menu_menu() {
     'type' => MENU_LOCAL_TASK,
     'weight' => 5,
   );
-  $items['admin/build/menu-customize/%menu'] = array(
+  $items['admin/build/menus/%menu'] = array(
     'title' => 'Customize menu',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_overview_form', 3),
@@ -84,47 +84,49 @@ function menu_menu() {
     'access arguments' => array('administer menu'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/build/menu-customize/%menu/list'] = array(
+  $items['admin/build/menus/%menu/list'] = array(
     'title' => 'List links',
     'weight' => -10,
     'type' => MENU_DEFAULT_LOCAL_TASK,
   );
-  $items['admin/build/menu-customize/%menu/add'] = array(
+  $items['admin/build/menus/%menu/add'] = array(
     'title' => 'Add link',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_edit_item', 'add', NULL, 3),
     'access arguments' => array('administer menu'),
     'type' => MENU_LOCAL_TASK,
   );
-  $items['admin/build/menu-customize/%menu/edit'] = array(
+  $items['admin/build/menus/%menu/edit'] = array(
     'title' => 'Edit menu',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_edit_menu', 'edit', 3),
     'access arguments' => array('administer menu'),
     'type' => MENU_LOCAL_TASK,
   );
-  $items['admin/build/menu-customize/%menu/delete'] = array(
+  $items['admin/build/menus/%menu/delete'] = array(
     'title' => 'Delete menu',
     'page callback' => 'menu_delete_menu_page',
     'page arguments' => array(3),
     'access arguments' => array('administer menu'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/build/menu/item/%menu_link/edit'] = array(
+  $items['admin/build/menus/%menu/%menu_link'] = array(
     'title' => 'Edit menu link',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_edit_item', 'edit', 4, NULL),
+    'title callback' => 'menu_item_title',
+    'title arguments' => array(4),
     'access arguments' => array('administer menu'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/build/menu/item/%menu_link/reset'] = array(
+  $items['admin/build/menus/%menu/%menu_link/reset'] = array(
     'title' => 'Reset menu link',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_reset_item_confirm', 4),
     'access arguments' => array('administer menu'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/build/menu/item/%menu_link/delete'] = array(
+  $items['admin/build/menus/%menu/%menu_link/delete'] = array(
     'title' => 'Delete menu link',
     'page callback' => 'menu_item_delete_page',
     'page arguments' => array(4),
@@ -157,8 +159,8 @@ function menu_theme() {
  */
 function menu_enable() {
   menu_rebuild();
-  $base_link = db_query("SELECT mlid AS plid, menu_name from {menu_links} WHERE link_path = 'admin/build/menu' AND module = 'system'")->fetchAssoc();
-  $base_link['router_path'] = 'admin/build/menu-customize/%';
+  $base_link = db_query("SELECT mlid AS plid, menu_name from {menu_links} WHERE link_path = 'admin/build/menus' AND module = 'system'")->fetchAssoc();
+  $base_link['router_path'] = 'admin/build/menus/%';
   $base_link['module'] = 'menu';
   $result = db_query("SELECT * FROM {menu_custom}", array(), array('fetch' => PDO::FETCH_ASSOC));
   foreach ($result as $menu) {
@@ -166,7 +168,7 @@ function menu_enable() {
     $link = $base_link;
     $link['mlid'] = 0;
     $link['link_title'] = $menu['title'];
-    $link['link_path'] = 'admin/build/menu-customize/' . $menu['menu_name'];
+    $link['link_path'] = 'admin/build/menus/' . $menu['menu_name'];
     $menu_link = db_query("SELECT mlid FROM {menu_links} WHERE link_path = :path AND plid = :plid", array(
       ':path' => $link['link_path'],
       ':plid' => $link['plid']
Index: modules/menu/menu.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.test,v
retrieving revision 1.15
diff -u -p -r1.15 menu.test
--- modules/menu/menu.test	24 May 2009 17:39:32 -0000	1.15
+++ modules/menu/menu.test	2 Jul 2009 19:40:10 -0000
@@ -97,7 +97,7 @@ class MenuTestCase extends DrupalWebTest
     // Add custom menu.
 
     // Try adding a menu using a menu_name that is too long.
-    $this->drupalGet('admin/build/menu/add');
+    $this->drupalGet('admin/build/menus/add');
     $menu_name = substr(md5($this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI + 1);
     $title = $this->randomName(16);
     $edit = array(
@@ -105,7 +105,7 @@ class MenuTestCase extends DrupalWebTest
       'description' => '',
       'title' =>  $title,
     );
-    $this->drupalPost('admin/build/menu/add', $edit, t('Save'));
+    $this->drupalPost('admin/build/menus/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.'));
@@ -113,13 +113,13 @@ class MenuTestCase extends DrupalWebTest
     // Change the menu_name so it no longer exceeds the maximum length.
     $menu_name = substr(md5($this->randomName(16)), 0, MENU_MAX_MENU_NAME_LENGTH_UI);
     $edit['menu_name'] = $menu_name;
-    $this->drupalPost('admin/build/menu/add', $edit, t('Save'));
+    $this->drupalPost('admin/build/menus/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.'));
     // Unlike most other modules, there is no confirmation message displayed.
 
-    $this->drupalGet('admin/build/menu');
+    $this->drupalGet('admin/build/menus');
     $this->assertText($title, 'Menu created');
 
     // Enable the custom menu block.
@@ -143,7 +143,7 @@ class MenuTestCase extends DrupalWebTest
     $title = $this->menu['title'];
 
     // Delete custom menu.
-    $this->drupalPost("admin/build/menu-customize/$menu_name/delete", array(), t('Delete'));
+    $this->drupalPost("admin/build/menus/$menu_name/delete", array(), t('Delete'));
     $this->assertResponse(200);
     $this->assertRaw(t('The custom menu %title has been deleted.', array('%title' => $title)), t('Custom menu was deleted'));
     $this->assertFalse(menu_load($menu_name), 'Custom menu was deleted');
@@ -181,7 +181,7 @@ class MenuTestCase extends DrupalWebTest
     // Note in the UI the 'mlid:x[hidden]' form element maps to enabled, or
     // NOT hidden.
     $edit['mlid:' . $item1['mlid'] . '[hidden]'] = TRUE;
-    $this->drupalPost('admin/build/menu-customize/' . $item1['menu_name'], $edit, t('Save configuration'));
+    $this->drupalPost('admin/build/menus/' . $item1['menu_name'], $edit, t('Save configuration'));
 
     // Verify in the database.
     $hidden = db_query("SELECT hidden FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $item1['mlid']))->fetchField();
@@ -202,7 +202,7 @@ class MenuTestCase extends DrupalWebTest
    */
   function addMenuLink($plid = 0, $link = '<front>', $menu_name = 'navigation') {
     // View add menu link page.
-    $this->drupalGet("admin/build/menu-customize/$menu_name/add");
+    $this->drupalGet("admin/build/menus/$menu_name/add");
     $this->assertResponse(200);
 
     $title = '!link_' . $this->randomName(16);
@@ -217,7 +217,7 @@ class MenuTestCase extends DrupalWebTest
     );
 
     // Add menu link.
-    $this->drupalPost("admin/build/menu-customize/$menu_name/add", $edit, t('Save'));
+    $this->drupalPost("admin/build/menus/$menu_name/add", $edit, t('Save'));
     $this->assertResponse(200);
     // Unlike most other modules, there is no confirmation message displayed.
 
@@ -254,7 +254,7 @@ class MenuTestCase extends DrupalWebTest
         'menu[link_path]' => $link_path,
         'menu[link_title]' => 'title',
       );
-      $this->drupalPost("admin/build/menu-customize/$menu_name/add", $edit, t('Save'));
+      $this->drupalPost("admin/build/menus/$menu_name/add", $edit, t('Save'));
       $this->assertRaw(t("The path '@path' is either invalid or you do not have access to it.", array('@path' => $link_path)), 'Menu link was not created');
     }
   }
@@ -304,16 +304,17 @@ class MenuTestCase extends DrupalWebTest
 
     $mlid = $item['mlid'];
     $title = $item['link_title'];
+    $menu_name = $item['menu_name'];
 
     // Edit menu link.
     $edit = array();
     $edit['menu[link_title]'] = $title;
-    $this->drupalPost("admin/build/menu/item/$mlid/edit", $edit, t('Save'));
+    $this->drupalPost("admin/build/menus/$menu_name/$mlid/edit", $edit, t('Save'));
     $this->assertResponse(200);
     // Unlike most other modules, there is no confirmation message displayed.
 
     // Verify menu link.
-    $this->drupalGet('admin/build/menu-customize/' . $item['menu_name']);
+    $this->drupalGet('admin/build/menus/' . $item['menu_name']);
     $this->assertText($title, 'Menu link was edited');
   }
 
@@ -326,9 +327,10 @@ class MenuTestCase extends DrupalWebTest
   function resetMenuLink($item, $old_title) {
     $mlid = $item['mlid'];
     $title = $item['link_title'];
+    $menu_name = $item['menu_name'];
 
     // Reset menu link.
-    $this->drupalPost("admin/build/menu/item/$mlid/reset", array(), t('Reset'));
+    $this->drupalPost("admin/build/menus/$menu_name/$mlid/reset", array(), t('Reset'));
     $this->assertResponse(200);
     $this->assertRaw(t('The menu link was reset to its default settings.'), t('Menu link was reset'));
 
@@ -349,9 +351,10 @@ class MenuTestCase extends DrupalWebTest
   function deleteMenuLink($item) {
     $mlid = $item['mlid'];
     $title = $item['link_title'];
+    $menu_name = $item['menu_name'];
 
     // Delete menu link.
-    $this->drupalPost("admin/build/menu/item/$mlid/delete", array(), t('Confirm'));
+    $this->drupalPost("admin/build/menus/$menu_name/$mlid/delete", array(), t('Confirm'));
     $this->assertResponse(200);
     $this->assertRaw(t('The menu link %title has been deleted.', array('%title' => $title)), t('Menu link was deleted'));
 
@@ -387,8 +390,9 @@ class MenuTestCase extends DrupalWebTest
    */
   function disableMenuLink($item) {
     $mlid = $item['mlid'];
+    $menu_name = $item['menu_name'];
     $edit['menu[enabled]'] = FALSE;
-    $this->drupalPost("admin/build/menu/item/$mlid/edit", $edit, t('Save'));
+    $this->drupalPost("admin/build/menus/$menu_name/$mlid/edit", $edit, t('Save'));
 
     // Unlike most other modules, there is no confirmation message displayed.
     // Verify in the database.
@@ -404,8 +408,9 @@ class MenuTestCase extends DrupalWebTest
    */
   function enableMenuLink($item) {
     $mlid = $item['mlid'];
+    $menu_name = $item['menu_name'];
     $edit['menu[enabled]'] = TRUE;
-    $this->drupalPost("admin/build/menu/item/$mlid/edit", $edit, t('Save'));
+    $this->drupalPost("admin/build/menus/$menu_name/$mlid/edit", $edit, t('Save'));
 
     // Verify in the database.
     $hidden = db_query("SELECT hidden FROM {menu_links} WHERE mlid = :mlid", array(':mlid' => $mlid))->fetchField();
@@ -440,14 +445,14 @@ class MenuTestCase extends DrupalWebTest
     }
 
     // View menu build overview node.
-    $this->drupalGet('admin/build/menu');
+    $this->drupalGet('admin/build/menus');
     $this->assertResponse($response);
     if ($response == 200) {
       $this->assertText(t('Menus'), t('Menu build overview node was displayed'));
     }
 
     // View navigation menu customization node.
-    $this->drupalGet('admin/build/menu-customize/navigation');
+    $this->drupalGet('admin/build/menus/navigation');
         $this->assertResponse($response);
     if ($response == 200) {
       $this->assertText(t('Navigation'), t('Navigation menu node was displayed'));
@@ -455,21 +460,21 @@ class MenuTestCase extends DrupalWebTest
 
     // View menu edit node.
     $item = $this->getStandardMenuLink();
-    $this->drupalGet('admin/build/menu/item/' . $item['mlid'] . '/edit');
+    $this->drupalGet('admin/build/menus/' . $item['menu_name'] . '/' . $item['mlid'] . '/edit');
     $this->assertResponse($response);
     if ($response == 200) {
       $this->assertText(t('Edit menu item'), t('Menu edit node was displayed'));
     }
 
     // View menu settings node.
-    $this->drupalGet('admin/build/menu/settings');
+    $this->drupalGet('admin/build/menus/settings');
     $this->assertResponse($response);
     if ($response == 200) {
       $this->assertText(t('Menus'), t('Menu settings node was displayed'));
     }
 
     // View add menu node.
-    $this->drupalGet('admin/build/menu/add');
+    $this->drupalGet('admin/build/menus/add');
     $this->assertResponse($response);
     if ($response == 200) {
       $this->assertText(t('Menus'), t('Add menu node was displayed'));
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.79
diff -u -p -r1.79 content_types.inc
--- modules/node/content_types.inc	1 Jul 2009 12:10:32 -0000	1.79
+++ modules/node/content_types.inc	2 Jul 2009 19:40:10 -0000
@@ -21,11 +21,11 @@ function node_overview_types() {
       $type_url_str = str_replace('_', '-', $type->type);
       $row = array(theme('node_admin_overview', $name, $type));
       // Set the edit column.
-      $row[] = array('data' => l(t('edit'), 'admin/build/node-type/' . $type_url_str));
+      $row[] = array('data' => l(t('edit'), 'admin/build/types/' . $type_url_str));
 
       // Set the delete column.
       if ($type->custom) {
-        $row[] = array('data' => l(t('delete'), 'admin/build/node-type/' . $type_url_str . '/delete'));
+        $row[] = array('data' => l(t('delete'), 'admin/build/types/' . $type_url_str . '/delete'));
       }
       else {
         $row[] = array('data' => '');
@@ -269,8 +269,9 @@ function node_type_form_validate($form, 
     }
     // 'theme' conflicts with theme_node_form().
     // '0' is invalid, since elsewhere we check it using empty().
-    if (in_array($type->type, array('0', 'theme'))) {
-      form_set_error('type', t("Invalid machine-readable name. Please enter a name other than %invalid.", array('%invalid' => $type->type)));
+    $reserved = array('0', 'theme') + menu_path_reserved_words('admin/build/types');
+    if (in_array($type->type, $reserved) && $type->type != $old_type) {
+      form_set_error('type', t('The machine-readable name %type may not be used because it is a reserved word.', array('%type' => $type->type)));
     }
   }
 
@@ -314,7 +315,7 @@ function node_type_form_submit($form, &$
     node_type_reset($type);
   }
   elseif ($op == t('Delete content type')) {
-    $form_state['redirect'] = 'admin/build/node-type/' . str_replace('_', '-', $type->old_type) . '/delete';
+    $form_state['redirect'] = 'admin/build/types/' . str_replace('_', '-', $type->old_type) . '/delete';
     return;
   }
 
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1077
diff -u -p -r1.1077 node.module
--- modules/node/node.module	2 Jul 2009 04:27:23 -0000	1.1077
+++ modules/node/node.module	2 Jul 2009 19:40:11 -0000
@@ -1722,18 +1722,18 @@ function node_menu() {
       'access arguments' => array('create', $type->type),
       'description' => $type->description,
     );
-    $items['admin/build/node-type/' . $type_url_str] = array(
+    $items['admin/build/types/' . $type_url_str] = array(
       'title' => $type->name,
       'page callback' => 'drupal_get_form',
       'page arguments' => array('node_type_form', $type),
       'access arguments' => array('administer content types'),
       'type' => MENU_CALLBACK,
     );
-    $items['admin/build/node-type/' . $type_url_str . '/edit'] = array(
+    $items['admin/build/types/' . $type_url_str . '/edit'] = array(
       'title' => 'Edit',
       'type' => MENU_DEFAULT_LOCAL_TASK,
     );
-    $items['admin/build/node-type/' . $type_url_str . '/delete'] = array(
+    $items['admin/build/types/' . $type_url_str . '/delete'] = array(
       'title' => 'Delete',
       'page arguments' => array('node_type_delete_confirm', $type),
       'access arguments' => array('administer content types'),
Index: modules/node/node.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.test,v
retrieving revision 1.34
diff -u -p -r1.34 node.test
--- modules/node/node.test	1 Jul 2009 12:10:32 -0000	1.34
+++ modules/node/node.test	2 Jul 2009 19:40:11 -0000
@@ -397,7 +397,7 @@ class SummaryLengthTestCase extends Drup
     $edit = array (
       'teaser_length' => 200,
     );
-    $this->drupalPost('admin/build/node-type/page', $edit, t('Save content type'));
+    $this->drupalPost('admin/build/types/page', $edit, t('Save content type'));
     // Attempt to access the front page again and check if the summary is now only 200 characters in length.
     $this->drupalGet("node");
     $this->assertNoRaw($expected, t('Check that the summary is not longer than 200 characters'), 'Node');
@@ -495,7 +495,7 @@ class NodePostSettingsTestCase extends D
     // Set page content type to display post information.
     $edit = array();
     $edit['node_submitted'] = TRUE;
-    $this->drupalPost('admin/build/node-type/page', $edit, t('Save content type'));
+    $this->drupalPost('admin/build/types/page', $edit, t('Save content type'));
 
     // Create a node.
     $edit = array();
@@ -516,7 +516,7 @@ class NodePostSettingsTestCase extends D
     // Set page content type to display post information.
     $edit = array();
     $edit['node_submitted'] = FALSE;
-    $this->drupalPost('admin/build/node-type/page', $edit, t('Save content type'));
+    $this->drupalPost('admin/build/types/page', $edit, t('Save content type'));
 
     // Create a node.
     $edit = array();
Index: modules/translation/translation.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/translation/translation.test,v
retrieving revision 1.12
diff -u -p -r1.12 translation.test
--- modules/translation/translation.test	12 Jun 2009 08:39:40 -0000	1.12
+++ modules/translation/translation.test	2 Jul 2009 19:40:12 -0000
@@ -31,10 +31,10 @@ class TranslationTestCase extends Drupal
     $this->addLanguage('es');
 
     // Set page content type to use multilingual support with translation.
-    $this->drupalGet('admin/build/node-type/page');
+    $this->drupalGet('admin/build/types/page');
     $edit = array();
     $edit['language_content_type'] = 2;
-    $this->drupalPost('admin/build/node-type/page', $edit, t('Save content type'));
+    $this->drupalPost('admin/build/types/page', $edit, t('Save content type'));
     $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Page')), t('Page content type has been updated.'));
 
     $this->drupalLogout();
Index: profiles/default/default.profile
===================================================================
RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v
retrieving revision 1.51
diff -u -p -r1.51 default.profile
--- profiles/default/default.profile	27 Jun 2009 17:32:00 -0000	1.51
+++ profiles/default/default.profile	2 Jul 2009 19:40:12 -0000
@@ -234,7 +234,7 @@ function default_profile_tasks(&$task, $
   menu_rebuild();
 
   // Save some default links.
-  $link = array('link_path' => 'admin/build/menu-customize/main-menu/add', 'link_title' => 'Add a main menu link', 'menu_name' => 'main-menu');
+  $link = array('link_path' => 'admin/build/menus/main-menu/add', 'link_title' => 'Add a main menu link', 'menu_name' => 'main-menu');
   menu_link_save($link);
 }
 
