Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.504
diff -u -p -r1.504 theme.inc
--- includes/theme.inc	13 Aug 2009 03:05:54 -0000	1.504
+++ includes/theme.inc	14 Aug 2009 03:24:08 -0000
@@ -1264,17 +1264,34 @@ function theme_status_messages($display 
  *    - href: the link URL. If omitted, the 'title' is shown as a plain text item in the links list.
  *    - html: (optional) set this to TRUE if 'title' is HTML so it will be escaped.
  *   Array items are passed on to the l() function's $options parameter when creating the link.
+ * @param $header
+ *   An optional keyed array for a header to precede the links:
+ *    - title: the header text
+ *    - type: the type of header (e.g. "h2", "h3")
+ *    - class: (optional) a class for the header, e.g. "element-invisible"
+ *   Headers should be used on navigation menus and any list of links that
+ *   consistently appears on multiple pages. Even if the header is invisible
+ *   to sighted users, it allows screen-reader and keyboard only users to
+ *   navigate to the links.
  * @param $attributes
  *   A keyed array of attributes.
  * @return
  *   A string containing an unordered list of links.
  */
-function theme_links($links, $attributes = array('class' => 'links')) {
+function theme_links($links, $header = array(), $attributes = array('class' => 'links')) {
   global $language;
   $output = '';
 
   if (count($links) > 0) {
-    $output = '<ul' . drupal_attributes($attributes) . '>';
+    $output = '';
+    if (isset($header['title']) && isset($header['type'])) {
+      $output .= '<' . $header['type'] . (isset($header['class']) ?
+        drupal_attributes(array('class' => $header['class'])) : '') . '>';
+      $output .= check_plain($header['title']);
+      $output .= '</' . $header['type'] . '>';
+    }
+
+    $output .= '<ul' . drupal_attributes($attributes) . '>';
 
     $num_links = count($links);
     $i = 1;
Index: modules/system/page.tpl.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/page.tpl.php,v
retrieving revision 1.27
diff -u -p -r1.27 page.tpl.php
--- modules/system/page.tpl.php	3 Aug 2009 03:04:33 -0000	1.27
+++ modules/system/page.tpl.php	14 Aug 2009 03:24:08 -0000
@@ -154,7 +154,7 @@
 
     <?php if ($main_menu): ?>
       <div id="navigation"><div class="section">
-        <?php print theme('links', $main_menu, array('id' => 'main-menu', 'class' => 'links clearfix')); ?>
+        <?php print theme('links', $main_menu, array('title' => t('Main menu'), 'type' => 'h2'), array('id' => 'main-menu', 'class' => 'links clearfix')); ?>
       </div></div> <!-- /.section, /#navigation -->
     <?php endif; ?>
 
@@ -192,7 +192,7 @@
     </div></div> <!-- /#main, /#main-wrapper -->
 
     <div id="footer"><div class="section">
-      <?php print theme('links', $secondary_menu, array('id' => 'secondary-menu', 'class' => 'links clearfix')); ?>
+      <?php print theme('links', $secondary_menu, array('title' => t('Secondary menu'), 'type' => 'h2'), array('id' => 'secondary-menu', 'class' => 'links clearfix')); ?>
       <?php if ($footer): ?><div id="footer-region" class="region"><?php print $footer; ?></div><?php endif; ?>
     </div></div> <!-- /.section, /#footer -->
 
Index: themes/garland/template.php
===================================================================
RCS file: /cvs/drupal/drupal/themes/garland/template.php,v
retrieving revision 1.23
diff -u -p -r1.23 template.php
--- themes/garland/template.php	28 Jul 2009 10:09:25 -0000	1.23
+++ themes/garland/template.php	14 Aug 2009 03:24:08 -0000
@@ -19,8 +19,12 @@ function garland_breadcrumb($breadcrumb)
  */
 function garland_preprocess_page(&$vars) {
   $vars['tabs2'] = menu_secondary_local_tasks();
-  $vars['primary_nav'] = isset($vars['main_menu']) ? theme('links', $vars['main_menu'], array('class' => 'links main-menu')) : FALSE;
-  $vars['secondary_nav'] = isset($vars['secondary_menu']) ? theme('links', $vars['secondary_menu'], array('class' => 'links secondary-menu')) : FALSE;
+  $vars['primary_nav'] = isset($vars['main_menu']) ? theme('links', $vars['main_menu'], array(
+    'title' => t('Main menu'), 'type' => 'h2', 'class' => 'element-invisible'
+  ), array('class' => 'links main-menu')) : FALSE;
+  $vars['secondary_nav'] = isset($vars['secondary_menu']) ? theme('links', $vars['secondary_menu'], array(
+    'title' => t('Secondary menu'), 'type' => 'h2', 'class' => 'element-invisible'
+  ), array('class' => 'links secondary-menu')) : FALSE;
   $vars['ie_styles'] = garland_get_ie_styles();
 
   // Prepare header
