This post should be an entry point for a discussion about the localization mechanism of Drupal 6. I like Drupal a lot and I'm using it in several projects. Nevertheless, I think its localization system is not one of its strengths. It works pretty well as long as you either always translate all your content into all the enabled languages or you don't care about people not seeing some parts of your site because they have not been translated. But whenever you are trying to build a website with a proper language fallback you run into several issues. (With „proper language fallback“ I mean that a user always sees all content and its menu items even if it doesn't exist in the selected language.)

I see two major problems in the way multiple languages are handle in Drupal:

  1. To describe one piece of information I need multiple nodes (one per translation)
  2. The module i18n uses hook_db_rewrite_sql() to „filter“ the displayed content by language

1. One node per translation

The localization system in Drupal stores every translation of a source node in a separate node. This creates much redundancy as you duplicate menu items, taxonomy relations and more. Imagine building a website with 5 languages. You will end up with tons of nodes and 5 different menus (or one menu with 5 menu items per page). You'll have a huge mess in your menu handling and what is more, the translated menu items are totally redundant as they all point to the same piece of information. What we really want to store (as kind of „duplicate“) is only the translated content of a node and the translated name of the related menu link – not the relations!

2. hook_db_rewrite_sql() as language filter

I assume there is currently no way around the module i18n if you want to have translated content. This module offers you five different „content selection modes“ to choose which way Drupal shows your language dependent content.

The most intuitive to use for a fallback would be Mixed current language (if available) or default language (if not) and language neutral. It means that Drupal shows nodes in the selected language if available or in the default language if not whereas language neutral content is always displayed.

These modes are implemented using hook_db_rewrite_sql(). The problem is that this function, as it says in its description, is usually used for access control. So i18n restricts access to nodes that don't exist in the selected language or in the default language. This is okay as long as it is only used to display content. However, db_rewrite_sql() is also used by the menu system to hide menu items for nodes the user has no access for. This way menu items for nodes that don't exist in the selected language are not displayed. (See also http://drupal.org/node/346112)

Conclusion

I think Drupal should refrain from storing translations in separate nodes. I don't have a proper solution in mind right now but I think the information about the language belongs to the actual content so why not storing it in the same table? Currently „language“ is a field of table node whereas the content is stored in node_revision. Storing the language in node_revision would make much more sense to me. The decision which language to display would then be handled by the nodeapi.

Please free your mind on my thoughts.

Comments

vm’s picture

not a bad write up, I think I'd get this on the mailing lists to generate more discussion from the top down rather than the bottom up in the forums.

WorldFallz’s picture

Can't speak to #1, but as for #2 db_rewrite_sql has been removed from d7 so the d7 version of i18n will be forced to find an alternative approach.

miruoss’s picture

Okay, I wasn't aware of that. Well then I hope they're not just gonna implement hook_query_alter() and react on the node_access tag because if they do it that way, we would be at the same point as we are now.

WorldFallz’s picture

Then don't hope-- head over to the i18n project and get involved. ;-)