Steps to reproduce:

  • Enable contact module
  • Enable i18nmenu module
  • Active more than 1 language
  • Create the menu item under Primary links: "Contact us" and point it to path "contact" and say the language is English
  • Go to a page with a path that doesn't begin with 'admin'
  • Switch languages, the menu is shown in all languages

When you create menu items that point to nodes they only appear when the interface is in the correct language but the link to the contact page just stays there.

I've tried to look in the code to provide a patch but I cannot even find where the language for a menu item is stored. There is the hook_form_alter() in the i18nmenu module and that's it. If someone kan give me a tip maybe I can continue to investigate.

CommentFileSizeAuthor
#4 i18nmenu.patch864 bytesjax

Comments

jax’s picture

Apparently the menu system can save extra information. In i18nmenu_menu_link_alter() the extra information is set:

$item['options']['langcode'] = $item['language'];

I can then see this information in the menu_links table. But it gets ignored. The only reason that I can think of is that there is already a 'contact' entry in the table without language and that it picks that one when verifying the language.

jax’s picture

I'm going crazy. This:

  unset($tree[$index]);

Removes the links in the Navigation block. I just cannot find where the primarly-links are filtered..... frustrating!!!

jax’s picture

A summary of what I've found out. (This way I can continue where I left of.)

  1. menu_tree_page_data() loads all the menu items with that big query and puts it in $data['tree'].
    After the query all the menu items in all the languages are available.
  2. menu_tree_check_access() removes the menu items that should not be seen by the user.
    1. In menu_tree_check_access() after the db_query(db_rewrite_sql()) all the links to nodes in the correct language have their access set to TRUE.
    2. Then there is _menu_tree_check_access > _menu_link_translate > that loads the extra options and finally _menu_check_access is going to set access to TRUE for the contact forms since it does the access callback.

This means that:

  1. i18nmenu is completely useless for the moment since even if you don't set languages on the menu items it will work just the same because if the links are shown or not is decided by the language the link points to. The language you set for the menu item is completely ignored.
  2. I'm wondering if it will even be possible to hide the link to the contact page in other languages.
jax’s picture

Status: Active » Needs review
StatusFileSize
new864 bytes

This is one possible approach. For the menu items where a language is set we indicate that they're "special" by setting "alter". For these "special" items drupal_alter('translated_menu_link', $item, $map); is called. In that hook we set the access to FALSE for the items we don't want to see.

It's the only solution I can come up with for the moment so feedback is appreciated.

bloggeredit’s picture

I can't make your patch work for primary or secondary links. i18nmenu_translated_menu_link_alter only gets called for blocks.

There is a simple way of dealing with primary and secondary links in your theme template.php file. The primary_links and secondary_links arrays are passed to the function phptemplate_preprocess_page through the &$vars array. All you need to do is check for the presence of the langcode key in each primary_links and secondary_links item and unset the unwanted one.

In other words, in phptemplate_preprocess_page(&$vars):
Loop through each $vars['primary_links'] or $vars['secondary_links'] items
check for the langcode key
compare it to $vars['language']->language
unset the item if different

then call theme('links', $vars['primary_links'], your attributes array with style info goes here).

The module should take care of that but the above works fine.

jax’s picture

After you install the patch you should EDIT and SAVE all your menu items one by one with a language set so that the $item['options']['alter'] = TRUE; gets set.

Did you do that?

bloggeredit’s picture

No I didn't. You're right it makes sense!

Anonymous’s picture

Hi Jax,

too bad I missed your post before :-( I've done a lot of investigation in how i18menu works, see http://drupal.org/node/263717
I'm trying to deal with localizing menu entries while you use menu items with languages. Anyway, certain things in i18nmenu are never activated as long as you don't increase the i18nblocks module weight which in turn will call i18nmenu functions for every block. This was crucial for localizing menu entries, but maybe it also changes behaviour for menu items with languages.

Let me ask: If a menu item is only shown when the language of the page it points to matches the current language (assuming you have sth. like "show only current (and perhaps no language)" set, why does it make sense for menu items to have languages? I would like to understand that.

jax’s picture

Well, this behaviour comes from the D5 version of the module so I'm not completely sure if this is the best way to proceed in D6. One reason I can think of is that some pages have no language, like the "contact" page. So in the case of the contact page, if I have a 3-language site I'll have the menu entries

  • nl/contact "Contacteer ons"
  • fr/contact "Contactez-nous"
  • en/contact "Contact us"

With each entry having the correct language and it should only be shown when the user has chosen that language. With menu items having languages you have the most flexibility. When you set the language negotiation to "anything" you can have menu's with anything it you want. The thing is that the menu should filter on the language of menu items AND what the language negotiation is set to. Now the former wasn't happening at all.

Anonymous’s picture

I guess that's because it is very easy to set the language of a page while creating or editing it, while setting a menu items language is more "complicated" because you need to go to "administer menus". So I guess it's unlikely to find menu items with languages most of the time...

Also it could be problematic: what if a menu item with language "English" points to a page in language "French"? Should that menu item show up when language is english, although pointing to a page that is no english?

However, all I understand is that i18nmenu leaves menu items with languages alone...

jax’s picture

Indeed, CURRENTLY i18nmenu leaves menu items with languages alone. It seems that the only work on it is done to support the i18nblocks module. My patch is the first attempt to make the i18nmenu module function for more use cases.

If you want an English menu with items that point to French pages, why not? The only thing is that the module should warn when you have menu items that are incompatible with your current language negotiation settings. And I'm starting to wonder why the language isn't applied to menu's rather than menu items.

The current state of affairs is that i18n worked way better for D5 than D6. Developmentseed also promised an upgrade path from D5 i18n to D6 i18n but it seems they're not coming through and honestly, IMO, it was a crazy promise to make.

I think that this is an example where the new i18n features that have been imported into core come into conflict with the things that existed. I hope to have time one of the coming weeks to look at this further. The patch works for my current use case but is not ideal for bigger sites and it doesn't feel right.

otichy’s picture

I would be very interested in any neat solution for D6, since, as Jax said, the menu item visibility depends on the language of the node it points to. This is rather problematic if the content isn't a simple node, but something like a list of blog entries filtered by a taxonomy term or an alien URL. These might in fact be quite language specific, but Drupal does not recognise them as such and therefore menu items pointing to them will appear in all language versions. Interestingly, this does not seem to be a problem in primary-links, but in secondary-links (?!).

jax’s picture

Thus we need to work out how we would like menus to work. I need to look at the "language negotiation" thing some more because I thought that it means "show nodes of this language by default" but apparently it blocks access to the other languages as well. The two options I can think of are:

  1. Show all menu items with the current language in the menu.
  2. Show menu items to nodes to a valid language. "Valid" is determined by the language negotiation. (= current situation without a working i18nmodule).
  3. (2) + only menu items that have the current language

In D5 it worked as (1) and is the way I would want to have it work in D6 as well. So I'll try to cook up a patch but it will be hard since the menu item visibility is done in core and I'm not sure if you can intervene in that process through a module.

otichy’s picture

I'd imagine 1. would be the most transparent way to handle this. I can understand that it is much easier to set the language while adding a node and not having to set through the menu item as well. So it could be a combination od 1. & 2. The menu items without specified language version would be displayed if they point to nodes in a valid language. The menu item would be displayed in both language versions only if language is not specified for both the menu item itself and the node it points to.

jax’s picture

A combination of (1) and (2) it is. If no language is set on the menu item only show it if it points to a node that is visible under the current language negotiation settings. If a language is set on the item show it if the interface is in that language. I'll try to give this a go.

otichy’s picture

Great, that would help, thoughb I have just installed your hack and the heck it helps as well :)

jax’s picture

Well the patch above does exactly that and still works with the first beta of i18n module. So this is still ready for review.

jax’s picture

Status: Needs review » Needs work

The above is incorrect. Links that have a language but point to a node that has another language will still not be shown. That's the interesting part to investigate since the menu system uses #access to hide them.

jose reyero’s picture

Category: bug » feature
Priority: Normal » Minor

Hi,

First of all I wouldn't call this a bug, but a feature that it's not there.

For primary/secondary links, they should get translated when they are in a block (and only for known blocks), but not when generated by the theme itself.

I would advise this other approach for that: http://drupal.org/node/70194

The problem with 'language selection' mode is that it messes with the node permission system so nodes not matching the current mode will just not be accessible.

About link in one language pointing to a node in a different language, I really don't have the time for that, patches will be reviewed though.

(Done a quick reading of this long thread, if missed anything, please let me know....)

jax’s picture

@19:

I've tried the 'Language dependent variables' approach but it doesn't seem to work. The links in different language to the contact page keep appearing in all the menus. I've only enabled the Internationalization module for this, the is no language dependent module as far as I can see.

How can I verify that I'm using separate primary menus for each language? I'm also using D6 so the explanation at http://drupal.org/node/70194 isn't totally correct anymore.

UPDATE: It works as advertised (It was menu_primary_links_source in stead of menu_primary_menu). Thanks Jose!

jax’s picture

For me this ticket can be closed since it's possible to do what I wanted to do with the language dependent variables. I'm am wondering what the i18nmenu module is good for then.

jose reyero’s picture

Status: Needs work » Fixed

Updated the handbook about this, http://drupal.org/node/313302

Anonymous’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.