I had several problems when I was trying to setup a multilanguage site and translate the Menu items.
The menu active item was working only for the english language, then I made some changes in menu_set_active_item and now it's working. See the code below:
/**
* Sets the path of the active menu item.
* Changed by wundo (03/12/2005)
*/
function menu_set_active_item($path = NULL) {
static $stored_mid;
$menu = menu_get_menu();
if (is_null($stored_mid) || !empty($path)) {
if (empty($path)) {
/* wundo Menu Hack (03/12/2005)
$path = $_GET['q'];
*/
$path = _i18n_get_original_path();
$path = substr($path,strlen(i18n_get_lang_prefix($path)));
if($path[0] == '/')
$path = substr($path,1);
if(empty($path))
$path = $_GET['q'];
}
else {
$_GET['q'] = $path;
}
while ($path && !array_key_exists($path, $menu['path index'])) {
$path = substr($path, 0, strrpos($path, '/'));
}
$stored_mid = array_key_exists($path, $menu['path index']) ? $menu['path index'][$path] : 0;
$path = $_GET['q'];
// Search for default local tasks to activate instead of this item.
$continue = TRUE;
while ($continue) {
$continue = FALSE;
if (array_key_exists('children', $menu['items'][$stored_mid])) {
foreach ($menu['items'][$stored_mid]['children'] as $cid) {
if ($menu['items'][$cid]['type'] & MENU_LINKS_TO_PARENT) {
$stored_mid = $cid;
$continue = TRUE;
}
}
}
}
}
return $stored_mid;
}
Comments
Comment #1
richardb commentedThis didn't work for me... all pages just showed 'You are not authorised to view this page'
I noticed
$path = $_GET['q'];
returns something like node/82, while
$path = _i18n_get_original_path();
returns: en/mypage
Comment #2
Anonymous (not verified) commentedI spent several ours working on this issue and came to the conclusion that the solution is not as simple as wundo proposes. The reason is, that the menu-object, dynamically generated and stored in $menu, stores (besides a lot of additional stuff) the relation between path (as you defined in the menu-administration) and menuID. During setup and theming of the page, the menu-object is queried several times, e.g. to identify visibility, activity etc. of content elements and naturally to code the html of the menu itself.
As I understood, the menu-object tries to store the menupath in the normal form 'node/XXX', i.e. drupal tries to resolve aliased pathnames. If this cannot be done, the alias-string is stored.
In the case when you define an aliased nodepath (e.g. 'en/mypath') but a different menupath (e.g. 'mypath') the alias cannot be resolved. In this case, the variable $menu contains a menu-item pointing to 'mypath'. Drupal get's into trouble identifying the relation between menu and content, which results in the menu on your page not beeing expanded or activated.
Ok, this is not too complex, but the menu-object also stores data of submenus and page task-bars (i.e. child-menues). These child-menus (they are e.g. the 'show'|'translate'|'edit' task-bars of nodes) are shown on your current page, i.e. their parent-node exists and the path can be de-aliased) are identified in $menu by 'node/XXX/something' while the related menu-item still points to 'mypath'. So drupal get's lost when starting to analyse chield-menues.
What does this mean: The solution proposed by wundo does not generally solve the issue.
I will give it some additional thoughts, but probably go along the approach proposed in http://drupal.org/node/30331#comment-48083
This is from an administration and S/W point of view not too elegant, and you may endup with different menu-trees in different languages, but for the 'enduser' it may be simpler to attach content directly 1-to-1 to a well defined menuelement (especially when he works with menu_otf). ;-)
PS: Hmmm, just a thought for future implementations of i18n and core: How about automatically store a menu-item for each language while hiding this to the user.
Comment #3
Anonymous (not verified) commentedI think I found two possible solutions to this problem.
a) code a template_menu_item_link() function in your template that does all the analysis on active menu's, childs and task bars when themeing a menu-item. By this, a lot of analysis is done over and over again and you repeat what is already done in the core. Positive is that you omit drawbacks on other modules. (Hmmm, by the way I was suprised, that the activity of the menu is only identified late in the l() function!)
b) hack the menu.inc file to achieve, that the "missing links" in the menu-data-object are resolved directly after fetching the data from the DB. Doing this, no data is changed in the DB, the missing links are just resolved when the menupathes (e.g. when switching language or administering menues) need update.
After the lines
// Handle URL aliases if entered in menu administration.$item->path = drupal_get_normal_path($item->path);in the function _menu_build() insert the following hack:
I tested the patch with some modules and different types of pages. I only marginally tested it with e.g. taxonomy. Nevertheless, I hope the patch is quite robust, as it does not touch resolved menupath's or menu's that are hard linked to nodes.
Be aware, that this patch automatically links the menu with path "mypath" to the system path of the alias "current_lang_prefix/mypath" (with current_lang_prefix beeing the current language prefix, e.g. "en") when this alias exists.
Good luck.
bernhard
Comment #4
Anonymous (not verified) commentedsorry ... the line
$i18n_orphan_path_found = True;is not required and can be deleted. (It's just a leftover from the testing)Comment #5
mirek_ commentedhello
i'm fighting with the same problem - the menu links, that will point to the translated content. it seems, that your (bgkaempf) hack is usefull and it will work. but - in my case it doesnt work. so whats wrong? what i have to do to make it work? i've got the fresh installation of the drupal 4.6 and installed the i18n module from this link. do i have to install something more?
anyway. i am bit sad and confused, that at the project page is written, that last update was on December 2nd, 2005, but the downloadable version is dated to 4.6.0, 25/04/2005 - 02:15 and the cvs version is dated to March 6, 2005 - 20:15 (its older?). only when i look at the CVS messages for Internationalization i see something new. so - is there updated version of the i18n in one downloadable and usable package, that i can use? because - i am very interesting in this module. and i dont want to make my own hacks because of the hard way to upgrade to a newer version of drupal or just the module. probably the only way is to apply the patches from the very first beginning from the cvs. but - what about to release new running version of this module... hmm... :-/
i will apreciate any help. thanks a lot
Comment #6
Anonymous (not verified) commentedmirek,
I used exactly the same i18n download. This is the latest update, as it already includes the i18n menu modul.
When installing i18n: Did you properly install i18n, especially did you patch the corefiles as required by i18n (bootstrap.inc and common.inc)?
bernhard
PS: attached you find the patched core files as required by standard i18n (these are my builds of the standard i18n patches, they are not related the menu-hack I discussed above!).
Comment #7
wundo commentedbgkaempf,
I don't have time to try you review yet, but I have my patch running in some site ok.
I used the last version (in last november) of i18n if the bootstrap.inc and etc from the i18n cvs (already patched).
The problem is that the track don't work in my patch, as soon as possible I will try your patch.
Comment #8
mirek_ commentedto bgkaempf ;)
what i have done:
1. i installed the fress instalation of drupal 4.6.5
2. i downloaded the i18n module (from the module page), check the node page as translatable
3. i used patches available with the i18n module
3. added my language in localization (so i have english and slovak)
4. added language block (for easier language content switching)
5. i created simple content page to test it and created english and slovak translation
6. added the link of this content to the menu (english is node/3 and slovak is node/2 - in the menu is link to the slovak - node/2)
so - after applying your patch to the menu.inc still no change - the link is still pointing to the node/2 - doesnt matter, what language is selected. is there something more to do to make it work?
Comment #9
Anonymous (not verified) commentedmirek
sorry for answering late ... I am fighting with some other nodetypes and modules currently ;-).
you write:
6. added the link of this content to the menu (english is node/3 and slovak is node/2 - in the menu is link to the slovak - node/2)
So, when I understand you correctly, you connected the menu with node/2, i.e. you 'hard-linked' the menu-item to the slovak content-item. To make my solution run you would have to:
6.a. give a meaningful alias name to your nodes, e.g. 'welcome':
alias the english node to: en/welcome
alias the slovak node to: ??/welcome (with ?? the 2-letter abbreviation for slovak)
6.b create a menu entry, name it e.g. 'welcome' and point it to the path 'welcome'
My patch then enables the menu to connect to your nodes (en/welcome and ??/welcome) depending on the active language.
Hope this helps.
Comment #10
Roberto Gerola commentedHello.
I think I've found a very simple and global solution to this topic.
I've changed the function l() in common.inc in this manner :
This patch needs some rows of code to check for the availability of the i18n module.
It shoud work for every link, I've tested both for menu and primary links.
Bye.
Comment #11
hugues commentedAfter working with the code proposed by bgkaempf, I found a clean and final solution. The problem is that drupal_get_normal_path() needs the full content of the alias while the menu entries only contain the page name. Example: the menu entry points to "mypage", while the aliases to the pages are "en/mypage" or any "<language code>/mypage". Non i18n path aliases can also exist and should of course still work. Example: a page with no language assigned to it, that should display in any language: the menu entry and the alias should be the same and be just "mypage".
The code first checks whether drupal_get_normal_path() returned something different than what we had before, meaning an alias was found. If not, it passes the path through custom_url_rewrite() which adds the language code. After that, it rechecks whether drupal_get_normal_path() returned something different.
The only glitch is that when a new alias is made, the page admin/menu has to be accessed so the _menu_build() function get called and the menu is updated. The same page has of course also to be accessed after the code has been patched for it to work for the first time.
Here is the code:
Comment #12
jose reyero commentedThis version is not supported anymore