Solving your multilingual navigation issues with Entity Translation in Drupal 7

Ryan Weal

October 19, 2012

UPDATE: the D7 entity module has changed, and now has support for menus.

See my latest post on the topic for more up-to-date information. This blog post has been a long time coming. I have been using Entity Translation, Drupal 7's new interface to doing translations, for the better part of this past year. It has been an exciting adventure, but with every new way of doing things there are some dragons along the path. In this post, I think I have solved one of my last great challenges with it by using some new contrib modules, so I'm documenting my experience here so you do not have to have the same troubles. Entity Translation, for those who are not aware, is Drupal's transition to translating fields rather than translating nodes. You can read more about it on Gábor's site on Drupal7 Multilingual if you wish (you've probably already seen this page if you were searching around and landed here).

So what is wrong with Drupal's navigation menus when you use Entity Translation?

What is the best way to address these issues?

doesn't work is taking the language from the translated entity and putting that language setting into Drupal's standard "menu_links" table. Not ideal right? Well, there is a workaround. You see, it is possible to create a navigation menu in Drupal that is language-specific. So, if you take a step back and think about this, since each language version of an entity-node has it's own menu configuration, why not just localize the menu entirely? That way we don't care if the menu_link is language neutral. With this structure, as an example, the French editor when doing the menu settings on a node must only remember to place the French translation within the context of the other French postings. That is simple enough to explain to your users.

Other dragons? Other awesome things? There are not that many issues I have found yet since this module generates

real Drupal menu_links for the navigation menu you can use any modules that support using Drupal's nav menu system, but you might have to do it twice (or more, depending on how many languages you are supporting. Additional things you might want to think about:

What about the future? Eventually, when we get around to adopting Drupal8, menu navigation will probably be based on entities. So we're already inching toward the future by embracing entities for everything now! UPDATE: You may also be interested in my new

Entity Translation Tabs module! UPDATE 2: Keep in mind you don't need many i18n modules with this, and that some i18n modules cause a conflict. Only "Block languages" (i18n_block) and the core i18n modules are necessary for this configuration. Be sure to disable i18n multilingual select, i18n field translation, i18n path translation and i18n menu translation. For your convenience: drush pm-disable i18n_select i18n_field i18n_path i18n_menu UPDATE 3: i18n_taxonomy is OK. i18n_taxonomy might cause troubles too, but I have not tested this yet. I recommend the "Localize" option on your taxonomy, which requires you to put the default language version first, and the "title" module to replace the taxonomy term name interface. You may have to hook_form_alter your Views if you output your taxonomy as an exposed filter to put the translation. I put the following into my hook_form_alter function to make taxonomy make sense: if ('taxonomy_form_term' == $form_id) { drupal_set_message('Taxonomy terms must be set in English first. Then click "save and translate" and you can put the French version. You can then manage existing translations by going to the term using the translate tab.'); } if ('views_exposed_form' == $form_id) { global $language; // this uses French, but you could abstract it a bit. if ($language->language == 'fr') { $result = db_query("select * from {field_data_name_field} where language='fr'"); foreach ($result as $row) { if(isset($form['field_series_code_tid']['#options'][$row->entity_id])){ $form['field_series_code_tid']['#options'][$row->entity_id] = $row->name_field_value; } } } }

Written by:
Ryan Weal @ryan_weal
Web developer based in Montréal. I run Kafei Interactive Inc. Node.js, Vue.js, Cassandra. Distributed data. Hire us to help with your data-driven projects.