function _menu_link_translate

Provides menu link access control, translation, and argument handling.

This function is similar to _menu_translate(), but it also does link-specific preparation (such as always calling to_arg() functions).


$item: A menu link.

$translate: (optional) Whether to try to translate a link containing dynamic path argument placeholders (%) based on the menu router item of the current path. Defaults to FALSE. Internally used for breadcrumbs.

Return value

Returns the map of path arguments with objects loaded as defined in the $item['load_functions']. $item['access'] becomes TRUE if the item is accessible, FALSE otherwise. $item['href'] is generated from link_path, possibly by to_arg functions. $item['title'] is generated from link_title, and may be localized. $item['options'] is unserialized; it is also changed within the call here to $item['localized_options'] by _menu_item_localize().

Related topics

8 calls to _menu_link_translate()
book_link_load in drupal/modules/book/book.module
Gets a book menu link by its menu link ID.
drupal_valid_path in drupal/includes/
Checks a path exists and the current user has access to it.
menu_link_load in drupal/includes/
Gets a translated, access-checked menu link that is ready for rendering.
menu_set_active_trail in drupal/includes/
Sets the active trail (path to the menu tree root) of the current page.
system_admin_config_page in drupal/modules/system/
Menu callback; Provide the administration overview page.

... See full list


drupal/includes/, line 880
API for the Drupal menu system.


function _menu_link_translate(&$item, $translate = FALSE) {
  if (!is_array($item['options'])) {
    $item['options'] = unserialize($item['options']);
  if ($item['external']) {
    $item['access'] = 1;
    $map = array();
    $item['href'] = $item['link_path'];
    $item['title'] = $item['link_title'];
    $item['localized_options'] = $item['options'];
  else {

    // Complete the path of the menu link with elements from the current path,
    // if it contains dynamic placeholders (%).
    $map = explode('/', $item['link_path']);
    if (strpos($item['link_path'], '%') !== FALSE) {

      // Invoke registered to_arg callbacks.
      if (!empty($item['to_arg_functions'])) {
        _menu_link_map_translate($map, $item['to_arg_functions']);
      elseif ($translate && ($current_router_item = menu_get_item())) {

        // If $translate is TRUE, then this link is in the active trail.
        // Only translate paths within the current path.
        if (strpos($current_router_item['path'], $item['link_path']) === 0) {
          $count = count($map);
          $map = array_slice($current_router_item['original_map'], 0, $count);
          $item['original_map'] = $map;
          if (isset($current_router_item['map'])) {
            $item['map'] = array_slice($current_router_item['map'], 0, $count);

          // Reset access to check it (for the first time).
    $item['href'] = implode('/', $map);

    // Skip links containing untranslated arguments.
    if (strpos($item['href'], '%') !== FALSE) {
      $item['access'] = FALSE;
      return FALSE;

    // menu_tree_check_access() may set this ahead of time for links to nodes.
    if (!isset($item['access'])) {
      if (!empty($item['load_functions']) && !_menu_load_objects($item, $map)) {

        // An error occurred loading an object.
        $item['access'] = FALSE;
        return FALSE;
      _menu_check_access($item, $map);

    // For performance, don't localize a link the user can't access.
    if ($item['access']) {
      _menu_item_localize($item, $map, TRUE);

  // Allow other customizations - e.g. adding a page-specific query string to the
  // options array. For performance reasons we only invoke this hook if the link
  // has the 'alter' flag set in the options array.
  if (!empty($item['options']['alter'])) {
    drupal_alter('translated_menu_link', $item, $map);
  return $map;