Hello,
I was recently working on a site that was heavily multilingual. We have a specific menu for each language (e.g., primary-links-english, primary-links-german). Everything works well out-of-the-box except pages created with views, and some other non-node things. The problem we were encountering is that when I am viewing a views-based page in English, then switch to German, I would lose all of my menu_blocks that were set to "menu selected by the page" or they were defaulting to the first one found (primary-links-english) in our case. I could drag the German menu above the English one in the menu_block settings page, but that just made the opposite problem happen (English page would show German menu).

So, I wrote a little bit of code to add the option to only match menu items that match the language of the page/node/whatever you're currently viewing. It works great. If you're viewing a German page, it'll only find the menu trail based on menu items that are set to "German" as the language, or that are set to "All Languages" as the language. It seems to be working well for us, but may not be worth anything to anyone else. Here's the diff:

diff --git a/sites/all/modules/menu_block/menu_block.admin.inc b/sites/all/modules/menu_block/menu_block.admin.inc
index 88d1beb..35c4be7 100644
--- a/sites/all/modules/menu_block/menu_block.admin.inc
+++ b/sites/all/modules/menu_block/menu_block.admin.inc
@@ -428,6 +428,13 @@ function menu_block_admin_settings_form($form_state) {
     '#value' => '<p>' . t('The above list will <em>not</em> affect menu blocks that are configured to use a specific menu.') . '</p>',
   );
 
+  $form['match_active_language'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Multilingual site? When using "menu selected by the page," only match menu items in the active language.'),
+    '#description' => t(' If the user is viewing a node in German, only look for menu items that are in German or "All Languages." Make sure each menu item has a specific language set, unless you want the menu item to be a viable option no matter what language the user is currently viewing.'),
+    '#default_value' => variable_get('menu_block_match_active_language', 0),
+  );
+
   $form['submit'] = array(
     '#type' => 'submit',
     '#value' => t('Save configuration'),
@@ -454,6 +461,9 @@ function menu_block_admin_settings_form_submit($form, &$form_state) {
     $menu_order[$menu_name] = '';
   }
   variable_set('menu_block_menu_order', $menu_order);
+
+  // Set the Match Active Language variable
+  variable_set('menu_block_match_active_language', $form_state['values']['match_active_language']);
 }
 
 /**
diff --git a/sites/all/modules/menu_block/menu_block.module b/sites/all/modules/menu_block/menu_block.module
index 2dc1e9b..8b44bf0 100644
--- a/sites/all/modules/menu_block/menu_block.module
+++ b/sites/all/modules/menu_block/menu_block.module
@@ -253,13 +253,39 @@ function menu_tree_build($config) {
       }
     }
 
-    // Retrieve all the menus containing a link to the current page.
-    $result = db_query("SELECT menu_name FROM {menu_links} WHERE link_path = '%s'", $_GET['q'] ? $_GET['q'] : '<front>');
+    $match_active_language = variable_get('menu_block_match_active_language', 0);
+
+    if ($match_active_language) {
+      global $language;
+      $default_lang = language_default()->language;
+      // Retrieve all the menus containing a link to the current page (and include 'options' field to get langcode)
+      $result = db_query("SELECT menu_name, options FROM {menu_links} WHERE link_path = '%s'", $_GET['q'] ? $_GET['q'] : '<front>');
+    }
+    else {
+      // Retrieve all the menus containing a link to the current page.
+      $result = db_query("SELECT menu_name FROM {menu_links} WHERE link_path = '%s'", $_GET['q'] ? $_GET['q'] : '<front>');
+    }
+
     while ($item = db_fetch_array($result)) {
       // Check if the menu is in the list of available menus.
       if (isset($menu_order[$item['menu_name']])) {
         // Mark the menu.
-        $menu_order[$item['menu_name']] = MENU_TREE__CURRENT_PAGE_MENU;
+        if ($match_active_language) {
+          $item['options'] = unserialize($item['options']);
+          // Menu item language matches active language
+          $cond1 = ($item['options']['langcode'] == $language->language) ? TRUE : FALSE;
+          // Active language matches default AND menu item language matches default
+          $cond2 = ($language->language == $default_lang && $item['options']['langcode'] == $default_lang) ? TRUE : FALSE;
+          // Menu item does not have a language code specified
+          $cond3 = (!isset($item['options']['langcode'])) ? TRUE : FALSE;
+
+          if ($cond1 || $cond2 || $cond3) {
+            $menu_order[$item['menu_name']] = MENU_TREE__CURRENT_PAGE_MENU;
+          }
+        }
+        else {
+          $menu_order[$item['menu_name']] = MENU_TREE__CURRENT_PAGE_MENU;
+        }
       }
       else {
         // Check if the menu matches one of the available patterns.

Comments

jediger’s picture

I came up with a solution that relies on consistent menu naming convention and language name.

In menu_tree_build():

while ($item = db_fetch_array($result)) {
  // Check if the menu is in the list of available menus.
  if (isset($menu_order[$item['menu_name']])) {
    // Mark the menu.
    
    if ($match_active_language) {
      $item['options'] = unserialize($item['options']);
      // Menu item language matches active language
      $cond1 = ($item['options']['langcode'] == $language->language) ? TRUE : FALSE;
      // Active language matches default AND menu item language matches default
      $cond2 = ($language->language == $default_lang && $item['options']['langcode'] == $default_lang) ? TRUE : FALSE;
      // Menu item does not have a language code specified
      $cond3 = (!isset($item['options']['langcode'])) ? TRUE : FALSE;
			
      if ($cond1 || $cond2 || $cond3) {
        $menu_order[$item['menu_name']] = MENU_TREE__CURRENT_PAGE_MENU;
      }
    }
    else {
      $menu_order[$item['menu_name']] = MENU_TREE__CURRENT_PAGE_MENU;
    }
  }
  else {
    // Check if the menu matches one of the available patterns.
    if(empty($patterns)) {
    	$menu_order['menu-primary-' . strtolower($language->name)] = MENU_TREE__CURRENT_PAGE_MENU;
    }
    foreach (array_keys($patterns) as $pattern) {
      if (preg_match($pattern, $item['menu_name'])) {
        // Mark the menu.
        $menu_order[$pattern] = MENU_TREE__CURRENT_PAGE_MENU;
        // Store the actual menu name.
        $patterns[$pattern] = $item['menu_name'];
      }
    }
  }
}

The key here is:

if(empty($patterns)) {
    $menu_order['menu-primary-' . strtolower($language->name)] = MENU_TREE__CURRENT_PAGE_MENU;
}

If no patterns have been found, it tries to match the current language with a matching menu manually based on language name.

This will works as long as menus are named "menu-primary-languagename"

jediger’s picture

Issue summary: View changes

Meh... messed up description during paste...

JohnAlbin’s picture

Status: Active » Closed (won't fix)