Index: i18nmenu/i18nmenu.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/i18n/i18nmenu/Attic/i18nmenu.install,v
retrieving revision 1.1.2.4
diff -u -p -r1.1.2.4 i18nmenu.install
--- i18nmenu/i18nmenu.install	18 Jan 2009 17:52:23 -0000	1.1.2.4
+++ i18nmenu/i18nmenu.install	4 Jun 2010 10:11:12 -0000
@@ -14,4 +14,18 @@
 function i18nmenu_enable() {
   drupal_load('module', 'i18nstrings');
   i18nmenu_locale_refresh();
-}
\ No newline at end of file
+  i18nmenu_node_item_translations_refresh_all();
+}
+
+/**
+ * Implementation of hook_uninstall().
+ *
+ * Delete all variables.
+ */
+function i18nmenu_uninstall() {
+  $result = db_query('SELECT name FROM {variable} WHERE name LIKE \'i18nmenu_node_translation_%%\'');
+  while ($row = db_fetch_object($result)) {
+    variable_del($row->name);
+  }
+  i18nmenu_node_item_translations_refresh_all();
+}
Index: i18nmenu/i18nmenu.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/i18n/i18nmenu/i18nmenu.module,v
retrieving revision 1.2.2.21
diff -u -p -r1.2.2.21 i18nmenu.module
--- i18nmenu/i18nmenu.module	25 May 2010 13:57:20 -0000	1.2.2.21
+++ i18nmenu/i18nmenu.module	4 Jun 2010 10:29:45 -0000
@@ -58,6 +58,11 @@ function i18nmenu_menu_link_alter(&$item
     // Setting the alter option to true ensures that
     // hook_translated_menu_link_alter() will be called.
     $item['options']['alter'] = TRUE;
+    // We store here the current translation set to allow node translation.
+    $map = explode('/', $item['link_path']);
+    if ($map[0] == 'node' && isset($map[1])) {
+      $item['options']['translations'] = i18nmenu_get_node_translations($map[1]);
+    } 
   }
 }
 
@@ -71,6 +76,10 @@ function i18nmenu_menu_link_alter(&$item
 function i18nmenu_translated_menu_link_alter(&$item, $map) {
   if ($item['module'] == 'menu') {
     $item['title'] = _i18nmenu_get_item($item);
+    if ($nid = i18nmenu_node_translation($item, $map)) {
+      $map[1] = $nid;
+      $item['href'] = implode('/', $map);
+    }
   }
 }
 
@@ -233,14 +242,23 @@ function i18nmenu_get_router($path) {
 /**
  * Implementation of hook_form_form_id_alter().
  *
- * Register a submit callback to process menu title.
+ * Add a checkbox to the menu_edit_menu form to enable path translation for node
+ * links and register a submit callback to process menu title.
  */
 function i18nmenu_form_menu_edit_menu_alter(&$form, $form_state) {
+  $menu = $form['menu_name']['#value'];
+  $form['submit']['#weight'] = 9;
+  $form['i18nmenu_node_translation'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Enable node translation'),
+    '#description' => t('If this is checked node link paths will be replaced with the node translation paths where available.'),
+    '#default_value' => variable_get("i18nmenu_node_translation_$menu", FALSE),
+  );
   $form['#submit'][] = 'i18nmenu_menu_edit_menu_submit';
 }
 
 /**
- * Submit handler for the menu_edit_item form.
+ * Submit handler for the menu_edit_menu form.
  *
  * On menu item insert or update, save a translation record.
  */
@@ -254,6 +272,24 @@ function i18nmenu_menu_edit_menu_submit(
     }
     i18nstrings_update_string($context, $form_state['values']['title']);
   }
+
+  // Check the language selection mode and display a warning if it will not play
+  // well with node translation.
+  if (variable_get('i18n_selection_mode', 'simple') != 'off' && $form_state['values']['i18nmenu_node_translation']) {
+    module_load_include('inc', 'i18n', 'i18n.admin');
+    $modes = _i18n_selection_mode();
+    $args = array(
+      '!url' => url('admin/settings/language/i18n'),
+      '!mode' => $modes['off'],
+    );
+    $message = t('Node translation will work properly only if <a href="!url">content language negotiation</a> is set to <em>!mode</em>', $args);
+    drupal_set_message($message, 'warning');
+  }
+
+  // Save the node translation setting for the current menu.
+  $menu = $form['menu_name']['#value'];
+  $value = $form_state['values']['i18nmenu_node_translation'];
+  variable_set("i18nmenu_node_translation_$menu", $value);
 }
 
 /**
@@ -396,6 +432,10 @@ function i18nmenu_form_alter(&$form, &$f
 function i18nmenu_nodeapi(&$node, $op) {
   switch ($op) {
     case 'insert':
+      if (isset($node->translation_source)) {
+        $nids = i18nmenu_get_node_translations($node->translation_source->nid);
+        i18nmenu_node_item_translations_refresh($nids);
+      }
     case 'update':
       if (isset($node->menu)) {
         $item = $node->menu;
@@ -415,6 +455,10 @@ function i18nmenu_nodeapi(&$node, $op) {
       while ($m = db_fetch_array($result)) {
         _i18nmenu_delete_item($m['mlid']);
       }
+      if ($node->tnid) {
+        $nids = i18nmenu_get_node_translations($node->tnid);
+        i18nmenu_node_item_translations_refresh($nids);
+      }
       break;
     case 'prepare translation':
       if (empty($node->menu['mlid']) && !empty($node->translation_source)) {
@@ -427,3 +471,117 @@ function i18nmenu_nodeapi(&$node, $op) {
       break;
   }
 }
+
+/**
+ * Return the nid of the node translation for the given language if available.
+ */
+function i18nmenu_node_translation($item, $map, $langcode = NULL) {
+  if (empty($item['options']['translations']) || !variable_get("i18nmenu_node_translation_{$item['menu_name']}", FALSE)) {
+    return FALSE;
+  }
+
+  if (is_object($map[1])) {
+    if (empty($map[1]->tnid)) {
+      // No translations for this node.
+      return FALSE;
+    }
+    $nid = $map[1]->nid;
+  }
+  else {
+    $nid = $map[1];
+  }
+
+  if (empty($langcode)) {
+    global $language;
+    $langcode = $language->language;
+  }
+
+  // If the translation is available and is not the current element we use it.
+  $translations = $item['options']['translations'];
+  if (isset($translations[$language->language]) && $translations[$language->language] != $nid) {
+    return $translations[$language->language];
+  }
+
+  return FALSE;
+}
+
+/**
+ * Return an array of node translation nids keyed by language.
+ */
+function i18nmenu_get_node_translations($nid) {
+  static $translations = array();
+  if (!isset($translations[$nid])) {
+    $result = db_query("SELECT n.language, n.nid FROM {node} n WHERE n.tnid != 0 AND n.tnid = (SELECT n2.tnid FROM {node} n2 WHERE n2.nid = %d)", $nid);
+    while ($row = db_fetch_object($result)) {
+      $translations[$nid][$row->language] = $row->nid;
+    }
+  }
+  return $translations[$nid];
+}
+
+/**
+ * Implementation of hook_form_form_id_alter().
+ */
+function i18nmenu_form_i18n_node_select_translation_alter(&$form, $form_state) {
+  $form['#submit'][] = 'i18nmenu_node_translation_set_update';
+}
+
+/**
+ * Submit handler for i18n_node_select_translation form.
+ *
+ * Refresh menu items' translation cache if the translation set has changed.
+ */
+function i18nmenu_node_translation_set_update($form, &$form_state) {
+  $changed = FALSE;
+  $nids = array($form['node']['#value']->nid);
+
+  foreach ($form_state['values']['translations']['nid'] as $langcode => $nid) {
+    $previous = $form['translations']['nid'][$langcode]['#value'];
+    if ($previous != $nid) {
+      $changed = TRUE;
+    }
+    if ($previous) {
+      $nids[] = $previous;
+    }
+    if ($nid) {
+      $nids[] = $nid;
+    }
+  }
+
+  if ($changed) {
+    $nids = array_unique($nids);
+    i18nmenu_node_item_translations_refresh($nids);
+  }
+}
+
+/**
+ * Refresh the translation cache for any menu item belonging to the translation
+ * sets identified by the given nids.
+ */
+function i18nmenu_node_item_translations_refresh($nids) {
+  $conditions = implode(' OR ', array_fill(0, count($nids), "link_path LIKE 'node/%d%%'"));
+  $query = 'SELECT mlid FROM {menu_links} WHERE '. $conditions .' ORDER by mlid';
+  _i18nmenu_node_item_translations_refresh($query, $nids);
+}
+
+/**
+ * Refresh the translation cache for any menu item pointing to a node page.
+ */
+function i18nmenu_node_item_translations_refresh_all() {
+  // TODO: Consider using a batch process here.
+  $query = 'SELECT mlid FROM {menu_links} WHERE link_path LIKE \'node/%%\' ORDER by mlid';
+  _i18nmenu_node_item_translations_refresh($query);
+  watchdog('i18nmenu', 'Translation cache has been refreshed for all node menu items.', array(), WATCHDOG_INFO);
+}
+
+/**
+ * Helper function: actually refresh the menu items returned by the given query.
+ */
+function _i18nmenu_node_item_translations_refresh($query, $args = NULL) {
+  $result = db_query($query, $args);
+  while ($row = db_fetch_object($result)) {
+    // Refresh the item's translation cache.
+    $item = menu_link_load($row->mlid);
+    menu_link_save($item);
+  }
+}
