First, THX for Your work (i was doing very similar thing earlier, then found Your module has changed similar way i was trying to do, so i dropped mine and started using Your code :)!

Here's a patch i made to make user's menus translatable.
There's only one "minor" quirk with it - in menu settings (where admin can edit/add/etc.. menus) only menus and menu items in current language or "no language" are shown. I probably could make patch different way, but this way it's just a few lines of changes and looks clean (IMHO :).

Patch changes following files:
- includes/menu.inc
- modules/menu.module
- modules/user.module

It implements translation by adding "language" field to menu database table and letting admin select language for each menu and menu item. When there's "no language" set, menu is "universal". When language is set, menu/item will be shown only with the same locale set.
Additionally it changes menu cache, so each language has own menu cached (so cache doesn't have to be cleaned after each locale change).

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

ahwayakchih’s picture

FileSize
2.26 KB

Argh, first patch post and already mistake...

I forgot to add .mysql file, i'm sorry.

Now zip contains both .patch and .mysql :)

Jose Reyero’s picture

Interesting feature, maybe for next version...

I think the approach is the right one, but the patch has some basic problem. The site will break if you disable i18n.

One mid term goal with this module is to get the proposed patches accepted for Drupal core, so they should meet some basic requirements:

- Ability to enable/disable i18n module without breaking the site
- No trace of i18n when module is disabled -I mean the language field still showing up in the forms, or the language condition applying when selecting menu items.

doubtintom’s picture

I have need of this feature. I'll never need to turn it off for the site I'm working on.

This is a patch to 4.5.0. I don't suppose I'm lucky enough that it would work with 4.6.0?

Any advice, before I go digging into the PHP myself?

r2mahara’s picture

I've tried it and it doesn't work properly. It needs to be updated for 4.6.

I need menu translation as well. I can do without menus, but not the person I'm building the site for! They insist on translatable menus.

I've talked to the author of the patch and he says he'll try to get an update out as soon as possible. Hopefully something that Jose can include by default.

Hopefully we'll be hearing something soon.

doubtintom’s picture

I tried setting up two menus with the same items, one menu translated for each language. I intended to use "Page specific visibility settings" in the block configuration to have the menus replace each other using en/* and es/*. That just does not work. Apparently the block node detection misses the language code part of the URL. Too bad. Or does someone know a better way to specify the regular expression?

Anyway, thanks to Jose, ahwayakchih, r2mahara and everyone working on this issue.

doubtintom’s picture

Here is a workaround/hack for 4.6.0 to define separate user menus, one for each language. Then have them switch off and on using adminster->blocks->configure (a menu block)->"Page specific visibility settings". Use en/* to keep an es menu from showing on the en pages, and vice versa.

Look in block.module, around line number 470 for this existing code:

      // Match path if necessary
      if ($block['pages']) {
        $path = drupal_get_path_alias($_GET['q']);

then add the following below it:

 
     // if a language is enabled, prepend it to the path
     // This will allow blocked page specs to match on language
     $lang = i18n_get_lang($name);
     if (strlen($lang) > 0) {
         $path = $lang . '/' . $path;
     }

I have no idea yet what side effects this may create, just got it to work, but the menus are switching nicely. YMMV

jsaints’s picture

The patch in #6 is working great so far. No side effects.

Thanks!

toxic-1’s picture

Version: » 4.6.x-1.x-dev
Assigned: Unassigned » toxic-1
Category: feature » support

I have such problem

one of messages from logs:

Duplicate entry '0' for key 1 query: INSERT INTO menu (mid, pid, path, title, description, weight, type, language) VALUES (0, 0, '', 'Main menu', '', 0, 115, 'en') in D:\BigApache\docs\drupal\includes\database.mysql.inc on line 66.

what's wrong?

steffen’s picture

The patch works great, doubtintom! This solved a serious issue for me!

steffen’s picture

...that is, the patch works for showing boxes only when prepending box en/*

Arto’s picture

The core patch in #6 was a lifesaver, saved a lot of digging around to fix block-hiding & showing. However, I condensed the patch to a one-liner, in order to minimize changes in line numbering. So, add the following line in modules/block.module just after line 462 (this becomes line 463):

if (function_exists('i18n_get_lang') && strlen(i18n_get_lang($name)) > 0) $path = i18n_get_lang($name) . '/' . $path; // i18n patch

This also checks to see whether i18n is enabled in the first place, so it won't affect the working of the block module if i18n isn't enabled. The disadvantage compared to the code in #6 is that it calls i18n_get_lang two times, but hey, I want to keep it a simple one-liner.

loony’s picture

#6 works like a charm! THANK YOU!

lduperval’s picture

I tried #6 with Drupal 4.6.2 and I found a side effect:

All translated content on my site has a flag at the bottom to access the transleated content. What I've found is that that link is translated also. What happens is that the content is shown in the other language, but the menu remains in English.

L

mesca’s picture

I also found another side effect:
I've created two user menus (one for FRench language, the other for ENglish). In both, there is the aggregator tree:
- Aggregator
--- Categories
---- Sources
The aggregator submenu doesn't expand when this patch is applied. Any hint?

brevity’s picture

any idea how to get #13 fixed?

do we need to make an exception for <span class="i18n-link"> or is this a more general side-effect?

brevity’s picture

Implementing a setting/switch to turn off language links on bottom of pages:

i18n.module:

  $output .= t('<h2>Multilingual content</h2>' );
  foreach (node_list() as $node) {
    $subform.=form_checkbox(t($node), 'i18n_node_'.$node, 1, variable_get('i18n_node_'.$node, 0));
  }

  $output .= form_radios(t('Language page link'), 'i18n_show_links', variable_get('i18n_show_links', 1), array(t("Disabled"), t("Enabled")), t("Enable or disable the 'languages' links for each node."));
...

i18n.inc:

/**
 * Implementation of hook_link().
 */
function i18n_link($type, $node = NULL, $teaser = FALSE) {
  $links = array();
  if ($type == 'node' && !$teaser && variable_get('i18n_node_'.$node->type, 0) && variable_get('i18n_show_links',1)) {
...
ronsens’s picture

Another workaround which avoids the side effects of #6 (described in #13), because you don't have to use block and not to modify block.module.

I do one menu for each language I need, "hardcode" the menus in page.tpl.php (for that you need to have a phptemplate-based theme) by using the theme-menu_tree-function (as it is described here: http://nicklewis.smartcampaigns.com/a-practical-tutorial-on-drupals-menu...

In page.tpl.php you have to put in then:

<?php 
  $MenuLanguage1 = theme_menu_tree(menu number of created menu for language 1);
  $MenuLanguage2 = theme_menu_tree(menu number of created menu for language 2);
  
    if (i18n_get_lang() == 'url-part for language 1') { print $MenuLanguage1; } else {
	print $MenuLanguage2;
    }
?>

A concrete example: I want to have a bilingual site (German - English). The first menu I have created for German has the number 100 (how to get that number - see the link above ), the second menu for English has the number 200, than the code would be:

<?php 
  $MenuLanguage1 = theme_menu_tree(100);
  $MenuLanguage2 = theme_menu_tree(200);
  
    if (i18n_get_lang() == 'de') { print $MenuLanguage1; } else {
	print $MenuLanguage2;
    }
?>
brevity’s picture

issue #13:

in i18n.inc change line

$links[]= theme('i18n_link_name_flag', $lang, 'node/'. $trnode->nid);
to
$links[]= theme('i18n_link_name_flag', $lang, $lang.'/node/'. $trnode->nid);

This adds the appropriate 'en/' or 'whatever-language/your-content' is in front of the link.

Also great idea, ronsens/#17! But how do you style your menus?

ufku’s picture

Title: User menu translation » Here is a hack for user menu translation without i18n

translation may be done after the menu is created. This will not conflict with menu entries in database since the translation is done using the menu output. Here is an hack for menu.module's block hook. This hack will make all user created menus avaliable for translation.

replace this:


$data['subject'] = $menu['items'][$delta]['title'];
$data['content'] = '<div class="menu">'. theme('menu_tree', $delta) .'</div>' ;

with this:


$data['subject'] = t($menu['items'][$delta]['title']);
$data['content'] = '<div class="menu">'. preg_replace ("/(>[^<\w]*)(\w+[^<]*\w+)([^<\w]*<\/)/e", "'\\1'.t('\\2').'\\3'", theme('menu_tree', $delta)) .'</div>' ;

'preg replace' will replace all (word)s (beginning with a word character+any non "<" character+ending with a word character) with t(word). These words are between ">" and "</".

if you also want to see translated menu titles in admin/blocks page, you should replace "$blocks[$mid]['info'] = $menu['items'][$mid]['title'];" with "$blocks[$mid]['info'] = t($menu['items'][$mid]['title']);"

ufku’s picture

Title: Here is a hack for user menu translation without i18n » User menu translation

-

csimard’s picture

I tried #6 with Drupal 4.6.3 I have some problem

I can create menu in english and in french. They appear in the Database. But when I choose a language the effect is to disabled the block containing the other menu language.

If I select french. French menu appear but english menu block is disabled. So when I select english language, nothing appear except a empty space. I can come back to french.

So I have to go on admin/setting/block to reset the block where I wish... And the same problem begin again...

Any Idea ?

THX

Marc Bijl’s picture

Last week, I got i18n_menu.module from Jose Reyero (the maintainer of i18n.module). It's an additional module that can be saved in the same directory as i18n.module and it does a pretty good job translating user defined menus (by localization).

You can find it here: http://drupal.org/node/14783. The code can be found #21 and there's an additional statement #24. All in all it's kinda "sneak preview" as Jose is still working on it, but it already blows me away! May this can help...

David Lesieur’s picture

Here is a side-effect to #6: When the current page has a language-specific url alias, the patch prepends the alias with the language, even though the language is already part of the alias. For example, if we are on a page aliased by "en/news", the function ends up checking the page-specific visibility settings against "en/en/news" instead of "en/news", which of course does not work as intended.

I found no problem with normal paths, only with aliased paths.

So the following may replace #6 (I also included the function_exists check suggested in #11):

  // If a language is not part of the path, prepend the current language
  // to the path. This will allow blocked page specs to match on language.
  if (function_exists('i18n_get_lang') && ($lang = i18n_get_lang()) && !i18n_get_lang_prefix($path)) {
    $path = "$lang/$path";
  }
wundo’s picture

Ow, #6 works great for me, I also made some changes into menu.inc to make the menu active item work...
You can find my code here: http://drupal.org/node/41629

Jose Reyero’s picture

Status: Needs review » Fixed

I think this one is addressed by the new modules added into i18n: i18nmenu -translatable menu items- and i18nblocks -with which you can set up different menus for languages-

Anonymous’s picture

Status: Fixed » Closed (fixed)