Commit 7d4f2836 authored by Dries's avatar Dries

- Patch #128082 by Goba et al: Allow localization of built-in menu items.

parent b93ce19a
......@@ -349,7 +349,8 @@ function menu_execute_active_handler() {
}
/**
* Handles dynamic path translation and menu access control.
* Handles dynamic path translation, title and description translation and
* menu access control.
*
* When a user arrives on a page such as node/5, this function determines
* what "5" corresponds to, by inspecting the page's menu path definition,
......@@ -360,6 +361,10 @@ function menu_execute_active_handler() {
* contain these dynamic arguments, translating node/%node to node/5.
* This operation is called MENU_RENDER_LINK.
*
* Translation of menu item titles and descriptions are done here to
* allow for storage of English strings in the database, and be able to
* generate menus in the language required to generate the current page.
*
* @param $item
* A menu item object
* @param $map
......@@ -434,6 +439,35 @@ function _menu_translate(&$item, $map, $operation = MENU_HANDLE_REQUEST) {
}
}
$item->alias = TRUE;
// Translate the title to allow storage of English title strings
// in the database, yet be able to display them in the language
// required to generate the page in.
$callback = $item->title_callback;
// t() is a special case. Since it is used very close to all the time,
// we handle it directly instead of using indirect, slower methods.
if ($callback == 't') {
if (empty($item->title_arguments)) {
$item->title = t($item->title);
}
else {
$item->title = t($item->title, unserialize($item->title_arguments));
}
}
else {
if (empty($item->title_arguments)) {
$item->title = $callback($item->title);
}
else {
$item->title = call_user_func_array($callback, unserialize($item->title_arguments));
}
}
// Translate description, see the motivation above.
if (!empty($item->description)) {
$item->description = t($item->description);
}
return $map;
}
......@@ -816,6 +850,8 @@ function menu_rebuild() {
'_mleft' => 0,
'_mright' => 0,
'block callback' => '',
'title arguments' => array(),
'title callback' => 't',
'description' => '',
'position' => '',
'attributes' => '',
......@@ -826,6 +862,8 @@ function menu_rebuild() {
);
$link_path = $item['to_arg_functions'] ? $path : drupal_get_path_alias($path);
$item['title arguments'] = empty($item['title arguments']) ? '' : serialize($item['title arguments']);
if ($item['attributes']) {
$item['attributes'] = serialize($item['attributes']);
}
......@@ -845,17 +883,19 @@ function menu_rebuild() {
}
db_query("INSERT INTO {menu} (
mid, pid, path, load_functions, to_arg_functions,
access_callback, access_arguments, page_callback, page_arguments, fit,
number_parts, visible, parents, depth, has_children, tab, title, parent,
access_callback, access_arguments, page_callback, page_arguments,
title_callback, title_arguments, fit, number_parts, visible,
parents, depth, has_children, tab, title, parent,
type, mleft, mright, block_callback, description, position,
link_path, attributes, query, fragment, absolute, html)
VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, %d,
'%s', %d, %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s', '%s',
'%s', '%s', '%s', '%s', %d, %d)",
VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s',
%d, %d, %d, '%s', %d, %d, %d, '%s', '%s', '%s', %d, %d, '%s', '%s',
'%s', '%s', '%s', '%s', '%s', %d, %d)",
$item['_mid'], $item['_pid'], $path, $item['load_functions'],
$item['to_arg_functions'], $item['access callback'],
serialize($item['access arguments']), $item['page callback'],
serialize($item['page arguments']), $item['_fit'],
serialize($item['page arguments']), $item['title callback'],
$item['title arguments'], $item['_fit'],
$item['_number_parts'], $item['_visible'], $item['_parents'],
$item['_depth'], $has_children, $item['_tab'],
$item['title'], $item['parent'], $item['type'], $item['_mleft'],
......@@ -866,8 +906,6 @@ function menu_rebuild() {
}
}
function menu_renumber(&$tree) {
foreach ($tree as $key => $element) {
if (!isset($tree[$key]['_mleft'])) {
......
......@@ -53,13 +53,13 @@ function aggregator_theme() {
*/
function aggregator_menu() {
$items['admin/content/aggregator'] = array(
'title' => t('News aggregator'),
'description' => t("Configure which content your site aggregates from other sites, how often it polls them, and how they're categorized."),
'title' => 'News aggregator',
'description' => "Configure which content your site aggregates from other sites, how often it polls them, and how they're categorized.",
'page callback' => 'aggregator_admin_overview',
'access arguments' => array('administer news feeds'),
);
$items['admin/content/aggregator/add/feed'] = array(
'title' => t('Add feed'),
'title' => 'Add feed',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_feed'),
'access arguments' => array('administer news feeds'),
......@@ -67,7 +67,7 @@ function aggregator_menu() {
'parent' => 'admin/content/aggregator',
);
$items['admin/content/aggregator/add/category'] = array(
'title' => t('Add category'),
'title' => 'Add category',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_category'),
'access arguments' => array('administer news feeds'),
......@@ -75,26 +75,26 @@ function aggregator_menu() {
'parent' => 'admin/content/aggregator',
);
$items['admin/content/aggregator/remove/%aggregator_feed'] = array(
'title' => t('Remove items'),
'title' => 'Remove items',
'page callback' => 'aggregator_admin_remove_feed',
'page arguments' => array(4),
'access arguments' => array('administer news feeds'),
'type' => MENU_CALLBACK,
);
$items['admin/content/aggregator/update/%aggregator_feed'] = array(
'title' => t('Update items'),
'title' => 'Update items',
'page callback' => 'aggregator_admin_refresh_feed',
'page arguments' => array(4),
'access arguments' => array('administer news feeds'),
'type' => MENU_CALLBACK,
);
$items['admin/content/aggregator/list'] = array(
'title' => t('List'),
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/content/aggregator/settings'] = array(
'title' => t('Settings'),
'title' => 'Settings',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_admin_settings'),
'type' => MENU_LOCAL_TASK,
......@@ -102,28 +102,28 @@ function aggregator_menu() {
'access arguments' => array('administer news feeds'),
);
$items['aggregator'] = array(
'title' => t('News aggregator'),
'title' => 'News aggregator',
'page callback' => 'aggregator_page_last',
'access arguments' => array('access news feeds'),
'weight' => 5,
);
$items['aggregator/sources'] = array(
'title' => t('Sources'),
'title' => 'Sources',
'page callback' => 'aggregator_page_sources',
'access arguments' => array('access news feeds'));
$items['aggregator/categories'] = array(
'title' => t('Categories'),
'title' => 'Categories',
'page callback' => 'aggregator_page_categories',
'access callback' => '_aggregator_has_categories',
);
$items['aggregator/rss'] = array(
'title' => t('RSS feed'),
'title' => 'RSS feed',
'page callback' => 'aggregator_page_rss',
'access arguments' => array('access news feeds'),
'type' => MENU_CALLBACK,
);
$items['aggregator/opml'] = array(
'title' => t('OPML feed'),
'title' => 'OPML feed',
'page callback' => 'aggregator_page_opml',
'access arguments' => array('access news feeds'),
'type' => MENU_CALLBACK,
......@@ -138,19 +138,19 @@ function aggregator_menu() {
'access arguments' => array('access news feeds'),
);
$items[$path .'/view'] = array(
'title' => t('View'),
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[$path .'/categorize'] = array(
'title' => t('Categorize'),
'title' => 'Categorize',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_page_category'),
'access arguments' => array('administer news feeds', 2),
'type' => MENU_LOCAL_TASK,
);
$items[$path .'/configure'] = array(
'title' => t('Configure'),
'title' => 'Configure',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_category', 2),
'access arguments' => array('administer news feeds', 2),
......@@ -163,19 +163,19 @@ function aggregator_menu() {
'type' => MENU_CALLBACK,
);
$items['aggregator/sources/%aggregator_feed/view'] = array(
'title' => t('View'),
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['aggregator/sources/%aggregator_feed/categorize'] = array(
'title' => t('Categorize'),
'title' => 'Categorize',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_page_source'),
'access arguments' => array('administer news feeds'),
'type' => MENU_LOCAL_TASK,
);
$items['aggregator/sources/%aggregator_feed/configure'] = array(
'title' => t('Configure'),
'title' => 'Configure',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_feed', 2),
'access arguments' => array('administer news feeds'),
......@@ -183,14 +183,14 @@ function aggregator_menu() {
'weight' => 1,
);
$items['admin/content/aggregator/edit/feed/%aggregator_feed'] = array(
'title' => t('Edit feed'),
'title' => 'Edit feed',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_feed', 5),
'access arguments' => array('administer news feeds'),
'type' => MENU_CALLBACK,
);
$items['admin/content/aggregator/edit/category/%aggregator_category'] = array(
'title' => t('Edit category'),
'title' => 'Edit category',
'page callback' => 'drupal_get_form',
'page arguments' => array('aggregator_form_category', 5),
'access arguments' => array('administer news feeds'),
......
......@@ -71,36 +71,37 @@ function block_perm() {
*/
function block_menu() {
$items['admin/build/block'] = array(
'title' => t('Blocks'),
'description' => t('Configure what block content appears in your site\'s sidebars and other regions.'),
'title' => 'Blocks',
'description' => 'Configure what block content appears in your site\'s sidebars and other regions.',
'page callback' => 'drupal_get_form',
'page arguments' => array('block_admin_display'),
'access arguments' => array('administer blocks'),
);
$items['admin/build/block/list'] = array(
'title' => t('List'),
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/build/block/configure'] = array(
'title' => t('Configure block'),
'title' => 'Configure block',
'page arguments' => array('block_admin_configure'),
'type' => MENU_CALLBACK,
);
$items['admin/build/block/delete'] = array(
'title' => t('Delete block'),
'title' => 'Delete block',
'page arguments' => array('block_box_delete'),
'type' => MENU_CALLBACK,
);
$items['admin/build/block/add'] = array(
'title' => t('Add block'),
'title' => 'Add block',
'page arguments' => array('block_add_block_form'),
'type' => MENU_LOCAL_TASK,
);
$default = variable_get('theme_default', 'garland');
foreach (list_themes() as $key => $theme) {
$items['admin/build/block/list/'. $key] = array(
'title' => t('!key settings', array('!key' => $theme->info['name'])),
'title' => '!key settings',
'title arguments' => array('!key' => $theme->info['name']),
'page arguments' => array('block_admin_display', $key),
'type' => $key == $default ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
'weight' => $key == $default ? -10 : 0,
......
......@@ -253,13 +253,13 @@ function blog_link($type, $node = NULL, $teaser = FALSE) {
*/
function blog_menu() {
$items['blog'] = array(
'title' => t('Blogs'),
'title' => 'Blogs',
'page callback' => 'blog_page',
'access arguments' => array('access content'),
'type' => MENU_SUGGESTED_ITEM,
);
$items['blog/%user_current'] = array(
'title' => t('My blog'),
'title' => 'My blog',
'page arguments' => array(1),
'access arguments' => array('edit own blog'),
);
......
......@@ -553,14 +553,14 @@ function blogapi_admin_settings() {
function blogapi_menu() {
$items['blogapi/rsd'] = array(
'title' => t('RSD'),
'title' => 'RSD',
'page callback' => 'blogapi_rsd',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['admin/settings/blogapi'] = array(
'title' => t('Blog APIs'),
'description' => t('Configure which content types and engines external blog clients can use.'),
'title' => 'Blog APIs',
'description' => 'Configure which content types and engines external blog clients can use.',
'page callback' => 'drupal_get_form',
'page arguments' => array('blogapi_admin_settings'),
'access arguments' => array('administer site configuration'),
......
......@@ -104,24 +104,24 @@ function book_link($type, $node = NULL, $teaser = FALSE) {
*/
function book_menu() {
$items['admin/content/book'] = array(
'title' => t('Books'),
'description' => t("Manage site's books and orphaned book pages."),
'title' => 'Books',
'description' => "Manage site's books and orphaned book pages.",
'page callback' => 'book_admin',
'access arguments' => array('administer nodes'),
);
$items['admin/content/book/list'] = array(
'title' => t('List'),
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/content/book/orphan'] = array(
'title' => t('Orphan pages'),
'title' => 'Orphan pages',
'page callback' => 'drupal_get_form',
'page arguments' => array('book_admin_orphan'),
'type' => MENU_LOCAL_TASK,
'weight' => 8,
);
$items['book'] = array(
'title' => t('Books'),
'title' => 'Books',
'page callback' => 'book_render',
'access arguments' => array('access content'),
'type' => MENU_SUGGESTED_ITEM,
......@@ -132,7 +132,7 @@ function book_menu() {
'type' => MENU_CALLBACK,
);
$items['node/%node/outline'] = array(
'title' => t('Outline'),
'title' => 'Outline',
'page callback' => 'drupal_get_form',
'page arguments' => array('book_outline', 1),
'access callback' => '_book_outline_access',
......
......@@ -197,33 +197,33 @@ function _comment_view_access($node, $cid) {
*/
function comment_menu() {
$items['admin/content/comment'] = array(
'title' => t('Comments'),
'description' => t('List and edit site comments and the comment moderation queue.'),
'title' => 'Comments',
'description' => 'List and edit site comments and the comment moderation queue.',
'page callback' => 'comment_admin',
'access arguments' => array('administer comments'),
);
// Tabs:
$items['admin/content/comment/list'] = array(
'title' => t('List'),
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
// Subtabs:
$items['admin/content/comment/list/new'] = array(
'title' => t('Published comments'),
'title' => 'Published comments',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/content/comment/list/approval'] = array(
'title' => t('Approval queue'),
'title' => 'Approval queue',
'page arguments' => array('approval'),
'type' => MENU_LOCAL_TASK,
);
$items['admin/content/comment/settings'] = array(
'title' => t('Settings'),
'title' => 'Settings',
'page callback' => 'drupal_get_form',
'page arguments' => array('comment_admin_settings'),
'weight' => 10,
......@@ -231,20 +231,20 @@ function comment_menu() {
);
$items['comment/delete'] = array(
'title' => t('Delete comment'),
'title' => 'Delete comment',
'page callback' => 'comment_delete',
'access arguments' => array('administer comments'),
'type' => MENU_CALLBACK,
);
$items['comment/edit'] = array(
'title' => t('Edit comment'),
'title' => 'Edit comment',
'page callback' => 'comment_edit',
'access arguments' => array('post comments'),
'type' => MENU_CALLBACK,
);
$items['comment/reply/%node'] = array(
'title' => t('Reply to comment'),
'title' => 'Reply to comment',
'page callback' => 'comment_reply',
'page arguments' => array(2),
'access callback' => 'node_access',
......@@ -252,7 +252,7 @@ function comment_menu() {
'type' => MENU_CALLBACK,
);
$items['node/%node/%'] = array(
'title' => t('View'),
'title' => 'View',
'page callback' => 'node_page_view',
'page arguments' => array(1, 2),
'access callback' => '_comment_view_access',
......
......@@ -42,50 +42,50 @@ function contact_perm() {
*/
function contact_menu() {
$items['admin/build/contact'] = array(
'title' => t('Contact form'),
'description' => t('Create a system contact form and set up categories for the form to use.'),
'title' => 'Contact form',
'description' => 'Create a system contact form and set up categories for the form to use.',
'page callback' => 'contact_admin_categories',
'access arguments' => array('administer site configuration'),
);
$items['admin/build/contact/list'] = array(
'title' => t('List'),
'title' => 'List',
'page callback' => 'contact_admin_categories',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/build/contact/add'] = array(
'title' => t('Add category'),
'title' => 'Add category',
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_edit'),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items['admin/build/contact/edit'] = array(
'title' => t('Edit contact category'),
'title' => 'Edit contact category',
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_edit'),
'type' => MENU_CALLBACK,
);
$items['admin/build/contact/delete'] = array(
'title' => t('Delete contact'),
'title' => 'Delete contact',
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_delete'),
'type' => MENU_CALLBACK,
);
$items['admin/build/contact/settings'] = array(
'title' => t('Settings'),
'title' => 'Settings',
'page callback' => 'drupal_get_form',
'page arguments' => array('contact_admin_settings'),
'type' => MENU_LOCAL_TASK,
'weight' => 2,
);
$items['contact'] = array(
'title' => t('Contact'),
'title' => 'Contact',
'page callback' => 'contact_site_page',
'access arguments' => array('access site-wide contact form'),
'type' => MENU_SUGGESTED_ITEM,
);
$items['user/%user/contact'] = array(
'title' => t('Contact'),
'title' => 'Contact',
'page callback' => 'contact_user_page',
'page arguments' => array(1),
'type' => MENU_LOCAL_TASK,
......
......@@ -43,32 +43,32 @@ function dblog_theme() {
*/
function dblog_menu() {
$items['admin/settings/logging/dblog'] = array(
'title' => t('Database logging'),
'description' => t('Settings for logging to the Drupal database logs. This is the most common method for small to medium sites on shared hosting. The logs are viewable from the admin pages.'),
'title' => 'Database logging',
'description' => 'Settings for logging to the Drupal database logs. This is the most common method for small to medium sites on shared hosting. The logs are viewable from the admin pages.',
'page callback' => 'drupal_get_form',
'page arguments' => array('dblog_admin_settings'),
);
$items['admin/logs/dblog'] = array(
'title' => t('Recent log entries'),
'description' => t('View events that have recently been logged.'),
'title' => 'Recent log entries',
'description' => 'View events that have recently been logged.',
'page callback' => 'dblog_overview',
'weight' => -1,
);
$items['admin/logs/page-not-found'] = array(
'title' => t("Top 'page not found' errors"),
'description' => t("View 'page not found' errors (404s)."),
'title' => "Top 'page not found' errors",
'description' => "View 'page not found' errors (404s).",
'page callback' => 'dblog_top',
'page arguments' => array('page not found'),
);
$items['admin/logs/access-denied'] = array(
'title' => t("Top 'access denied' errors"),
'description' => t("View 'access denied' errors (403s)."),
'title' => "Top 'access denied' errors",
'description' => "View 'access denied' errors (403s).",
'page callback' => 'dblog_top',
'page arguments' => array('access denied'),
);
$items['admin/logs/event/%'] = array(
'title' => t('Details'),
'title' => 'Details',
'page callback' => 'dblog_event',
'page arguments' => array(3),
'type' => MENU_CALLBACK,
......
......@@ -349,22 +349,22 @@ function drupal_auth($username, $password, $server = FALSE) {
*/
function drupal_menu() {
$items['admin/settings/sites-registry'] = array(
'title' => t('Sites registry'),
'description' => t('Register with another Drupal site (drupal.org by default) for statistics sharing, or set up your server to be a central server for registrations.'),
'title' => 'Sites registry',
'description' => 'Register with another Drupal site (drupal.org by default) for statistics sharing, or set up your server to be a central server for registrations.',
'page callback' => 'drupal_get_form',
'page arguments' => array('drupal_sites_registry_settings'),
'access arguments' => array('administer site configuration'),
);
$items['admin/settings/distributed-authentication'] = array(
'title' => t('Distributed authentication'),
'description' => t('Allow your site to accept logins from other Drupal sites such as drupal.org.'),
'title' => 'Distributed authentication',
'description' => 'Allow your site to accept logins from other Drupal sites such as drupal.org.',
'page callback' => 'drupal_get_form',
'page arguments' => array('drupal_distributed_authentication_settings'),
'access arguments' => array('administer site configuration'),
);
if (variable_get('drupal_authentication_service', 0)) {
$items['drupal'] = array(
'title' => t('Drupal'),
'title' => 'Drupal',
'page callback' => 'drupal_page_help',
'access callback' => TRUE,
'type' => MENU_SUGGESTED_ITEM,
......
......@@ -72,31 +72,31 @@ function filter_theme() {
*/
function filter_menu() {
$items['admin/settings/filters'] = array(
'title' => t('Input formats'),
'description' => t('Configure how content input by users is filtered, including allowed HTML tags. Also allows enabling of module-provided filters.'),
'title' => 'Input formats',
'description' => 'Configure how content input by users is filtered, including allowed HTML tags. Also allows enabling of module-provided filters.',
'page callback' => 'drupal_get_form',
'page arguments' => array('filter_admin_overview'),
'access arguments' => array('administer filters'),
);
$items['admin/settings/filters/list'] = array(
'title' => t('List'),
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/settings/filters/add'] = array(
'title' => t('Add input format'),
'title' => 'Add input format',
'page callback' => 'drupal_get_form',
'page arguments' => array('filter_admin_format_form'),
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
$items['admin/settings/filters/delete'] = array(
'title' => t('Delete input format'),
'title' => 'Delete input format',
'page callback' => 'drupal_get_form',
'page arguments' => array('filter_admin_delete'),
'type' => MENU_CALLBACK,
);
$items['filter/tips'] = array(
'title' => t('Compose tips'),
'title' => 'Compose tips',
'page callback' => 'filter_tips_long',
'access callback' => TRUE,
'type' => MENU_SUGGESTED_ITEM,
......@@ -108,19 +108,19 @@ function filter_menu() {
);
$items['admin/settings/filters/%filter_format/list'] = array(
'title' => t('View'),
'title' => 'View',
'page arguments' => array('filter_admin_format_form', 3),
'type' => MENU_DEFAULT_LOCAL_TASK,