On this page
i18n module integration
Drupal 7 will no longer be supported after January 5, 2025. Learn more and find resources for Drupal 7 sites
There is a i18n controller for integration (exportable) entities with the i18n module. However, the controller requires some additional code for your entity type to be activated. It's best practice to create a small integration module for that, which then can depend upon i18n. In that module you basically have to:
- Activate the i18n integration controller.
- Declare translatable properties.
- Implement CRUD hooks to notify i18n module of updates
Once, you've done that you still have to take care of using the translation in the right place, e.g. with the provided helper entity_i18n_string()
. It's recommended to use classed entity objects in order to be able to leverage the simpler to use Entity::getTranslation()
method though.
Example
As example, we have a short look at the i18n integration provided by profile2:
The profile2_i18n.info file looks like this:
name = Profile2 translation
description = Translate profile2 types.
dependencies[] = profile2
dependencies[] = i18n_string
package = Multilingual - Internationalization
core = 7.x
Then the module file activates the entity i18n integration controller...
/**
* Implements hook_entity_info_alter().
*/
function profile2_i18n_entity_info_alter(&$info) {
// Enable i18n support via the entity API.
$info['profile2_type']['i18n controller class'] = 'EntityDefaultI18nStringController';
}
...and declares some properties as translatable:
/**
* Implements hook_entity_property_info_alter().
*/
function profile2_i18n_entity_property_info_alter(&$info) {
// Mark some properties as translatable, but also denote that translation
// works with i18n_string.
foreach (array('label') as $name) {
$info['profile2_type']['properties'][$name]['translatable'] = TRUE;
$info['profile2_type']['properties'][$name]['i18n string'] = TRUE;
}
}
What remains to be done is informing the i18n module about updates:
/**
* Implements hook_profile2_type_insert().
*/
function profile2_i18n_profile2_type_insert($profile_type) {
i18n_string_object_update('profile2_type', $profile_type);
}
/**
* Implements hook_profile2_type_update().
*/
function profile2_i18n_profile2_type_update($profile_type) {
// Account for name changes.
if ($profile_type->original->type != $profile_type->type) {
i18n_string_update_context("profile2:profile2_type:{$profile_type->original->type}:*", "profile2:profile2_type:{$profile_type->type}:*");
}
i18n_string_object_update('profile2_type', $profile_type);
}
/**
* Implements hook_profile2_type_delete().
*/
function profile2_i18n_profile2_type_delete($profile_type) {
i18n_string_object_remove('profile2_type', $profile_type);
}
That's it. Using translation usually has to be done in the main module, not depending on i18n - e.g. as done here:
return t('My @profile-label', array('@profile-label' => drupal_strtolower($type->getTranslation('label'))));
Further notes:
- In case your integration needs are more complex you can override the
EntityDefaultI18nStringController
and provide a customi18n_string_object_wrapper
, e.g. Rules does so. - Other example implementations can be found in Rules link, here or here.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion