What Developers Need to Know about Multilingual Drupal 7 Sites

Topics: 

When working with Drupal's language / locale components in code, we need to be aware of some issues to ensure that the multilingual subsystem works as we'd expect.

Hard-coding a language (or assuming no language) is problematic

When working with fields, developers often set or get field data by explicitly providing the undefined language (the standard one set up if the language system isn't, "LANGUAGE_NONE" defined as "und"). This will cause code to fail whenever the Entity Translation module is enabled with actual languages. Wouldn't it be better to have Drupal automatically work with the current language?

Retrieving field values

The fieldgetitems() API call does this for you. If you don't specify a language, it will default to the current language if one isn't specified. So if you really do want to target a specific language, you can.

For example,
$value = $node->field_subtitle[LANGUAGE_NONE][0]['value'];

...should generally be replaced with...

$field_items = field_get_items('node', $node, 'field_subtitle');
$value = $field_items[0]['value'];

Setting field values

Unfortunately, there's no field_set_items() function in Drupal 7. We can, however, still specify the current language when setting field data if we're working with translatable fields.

Instead of
$node->body[LANGUAGE_NONE][0]['format'] = 'full_html';

...you'll probably want to use one of the global variables $language (for the interface language) or $language_content (for the content language) as in ...

$langcode_current = $GLOBALS['language']->language;
$node->body[$langcode_current][0]['format'] = 'full_html';

Alternatives

Assuming the current language, the Entity API module actually provides both setter and getter methods through its Entity metadata wrappers. However, it's another dependency and extra overhead that you may not want if you're not using it already. It also makes things trickier to debug. See What's best practice when working with the language[und]? for a discussion on this.

Translatable title fields are actually different fields

By default, field translation through the Entity Translation module doesn't allow title fields to be translatable. This is because title fields in Drupal 7 aren't implemented formally as fields using the Field API. To get around this limitation, it's necessary to replace titles with translatable fields using the Title module.

To enable this for specific fields, it's necessary to click on the "replace" button for a title field in the Manage Fields tab for the content type / bundle. This will switch basic use cases over to use the new "field_title" field instead of the default "title" field.

Be aware that you'll have to update any views and custom code to use the new field. If not done, titles will always be presented in the original language, and you'll wonder why translated titles aren't showing up.

If you don't really need translated titles, it's best to leave the original titles as-is. Otherwise, it gets complicated with multiple title fields.

Comments

"This will cause code to fail

"This will cause code to fail whenever the Locale module is enabled (even if no additional languages are set up) because the default language then switches to something like "en"."

Umm, no, not at all!

Field language will always be LANGUAGE_NONE unless the Field Translation module (part of Entity Translation suite) is installed. For all other cases, even if using multilingual sites and even with translated content, the actual field's language will remain LANGUAGE_NONE!

$field_items = field_get


$field_items = field_get_items('node', $node, 'field_subtitle');
$value = $field_items[0]['value'];

Could end you up with undefined index errors if there are no field items.
It is better to first check that $field_items is not empty, like this:


if ($field_items = field_get_items('node', $node, 'field_subtitle')) {
$value = $field_items[0]['value'];
}

Add new comment