Drupal 6 and Primary/Secondary menu translation
I ran into the following issue while developing a bilingual (English and Spanish) site recently:
I wanted the site, for ease of use, to have a single menu structure so translators didn't have to worry about mimicking the primary navigation every time they translated a page or added a new one.
The problems, when the site was in Spanish, were three-fold:
- Primary links were linking to es/english-path even though es/spanish-path existed.
- For every sub item that was in English, when on the translated page, the secondary menu didn't display, since the menu system didn't see the translated page as a child of the parent.
- Both primary and secondary link text was still in English.
The 3 issues were solved as follows.
in theme_preprocess_page:
$vars['primary_links'] = _opensourcery_primary_links($vars['primary_links']); $vars['secondary_links'] = _opensourcery_secondary_links($vars['secondary_links']);
and these 2 functions look like this:
function _opensourcery_primary_links($primary) { global $language; foreach ($primary as $lid => $link) { $link = opensourcery_translate_translate_path($link); $primary[$lid] = $link; } return $primary; } function _opensourcery_secondary_links($secondary) { global $language; // This function call will rebuild the secondary menu as if the page were in // English, thus solving the second issue. if ($language->language == 'es') { $secondary = _opensourcery_rebuild_secondary_links(); } foreach ($secondary as $lid => $link) { $link = opensourcery_translate_translate_path($link); $primary[$lid] = $link; } return $secondary; }
As you can see, the key to each of these functions is the opensourcery_translate_translate_path($link) function, which looks like this:
/** * Translate a link array. */ function os_translate_translate_path($link) { global $language; // get a list of all available paths $new_paths = translation_path_get_translations($link['href']); if ($new_paths[$language->language]) { // if a translated path exists, set it here $link['href'] = $new_paths[$language->language]; } // translate the title (this adds every menu title to the locale_source // table, for later translation $link['title'] = t($link['title']); if ($link['attributes']['title']) { $link['attributes']['title'] = t($link['attributes']['title']); } return $link; }
The other key function is the one that rebuilds the second menu when viewing a page in Spanish:
function _opensourcery_rebuild_secondary_links() { // menus are built in English, so set active trail there $new_paths = translation_path_get_translations($_GET['q']); // save current path $current = $_GET['q']; if ($new_paths['en']) { menu_set_active_item($new_paths['en']); } $secondary_links = menu_secondary_links(); // reset active item menu_set_active_item($current); return $secondary_links; }
Those functions solved the translation issues, and allowed the site to have a single menu structure, without requiring site editors and translators to become involved in the menu system.

Comments
link alias
Hi,
Thanks this is excellent and very helpful. I have just one question though, I post some content just in the default language, or I have three languages and sometimes the content is only translated in two.. When this happens the link to the content just uses the node/34 rather than the alias.. I tried using this module (http://drupal.org/project/globalredirect) but it doesn't work with six.. Any ideas?
thanks
John
I know something special had
I know something special had to be done to get path aliases working across all languages, but I don't have the code in front of me at the moment. I'll post back once I figure out what we did.
Thank you!
Thank you, Jonathan.
Your blog post was extremely helpful in translating custom menus for the Custom Page module (http://drupal.org/project/custompage)
I am new to Drupal. Does
I am new to Drupal. Does this work for 6.3? I cannot find theme_preprocess_page; where is this file?
Hey Marc, The
Hey Marc,
The theme_preprocess_page is a function, rather than a file. For more information on how to use these theme hooks, you can use the Drupal Theme Guide. Specifically, see the part about preprocess functions.
Wow, there's quite a bit of
Wow, there's quite a bit of information here. Do I just add your $vars' to function template_preprocess_page in includes/theme.inc and add the three functions to includes/theme.inc?
Well I'm glad its possible,
Well I'm glad its possible, I've had a bit more of a mess about with it but still haven't quite got it working, any chance you've found the code you used?
cheers
John
Hey John, Oddly, I can't
Hey John,
Oddly, I can't find any explicit fixes for the alias issue mentioned above. I think for the site in question the menu tweaks in the original post took care of the issue. One possible explanation of this is that we aren't using the built in translation links that get tacked onto a node, but rather creating our own in the theme using this code:
The code above is appending a translate link to an existing array of links, but the key is the construction of the $path variable, since that is what gets replaced with a url alias. Let me know if that helps.
Post new comment