Old functions tt() and ts() have been deprecated. Use i18nstrings() and i18nstrings_update() instead.

The Internationalization module provides translation services for user-defined strings. It also tracks source strings and keeps them up-to-date using a 'string key' that is a string with these elements "textgroup:object_type:object_key:property_name".

Some examples of these 'string keys' are:

taxonomy:term:12:name
nodetype:type:story:name

For translating these strings, the module must call this function before displaying them:

/**
 * Translate or update user defined string.
 * 
 * @param $name
 *   Textgroup and location glued with ':'.
 * @param $string
 *   String in default language. Default language may or may not be English.
 * @param $langcode
 *   Optional language code if different from current request language.
 * 
 * @return $string
 *   Translated string, $string if not found
 */
function i18nstrings($name, $string, $langcode = NULL) {
   .....
}

For strings that have an input format, you must use the function i18nstrings_text() that takes care of applying the correct filters if there is a translation.

/**
 * Get filtered translation
 * 
 * This function is intended to return translations for strings that have an input format
 * 
 * @param $name
 *   Full string id
 * @param $default
 *   Default string to return if not found, already filtered
 * @param $langcode
 *   Optional language code if different from current request language.
 */
function i18nstrings_text($name, $default, $langcode = NULL) {
  ....
}

Most Drupal core 'textgroups' and strings like Taxonomy terms, Vocabularies, Menu items, or Content type names are already defined and tracked by the Internationalization package modules so the only thing you need is the translating function above. When a module defines its own strings, it must use some additional functions to allow these string to be tracked and updated.

1. Define the textgroup by implementing hook_locale(). This is how it looks in the Taxonomy translation module:

/**
 * Implementation of hook_locale().
 */
function i18ntaxonomy_locale($op = 'groups', $group = NULL) {
  switch ($op) {
    case 'groups':  // This is the standard hook_locale() as defined by Drupal core, to define 'text groups'
      return array('taxonomy' => t('Taxonomy'));

    case 'info':  // This is i18n extension, optional, to define additional properties
      // Optional refresh callback to update this module's strings at once
      $info['taxonomy']['refresh callback'] = 'i18ntaxonomy_locale_refresh';
      // This tells 'i18nstrings' that this module's strings have no input format applied
      $info['taxonomy']['format'] = FALSE;
      return $info;
  }
}

2. Use i18nstrings_update() whenever the source string changes.

/**
 * Update / create translation source for user defined strings.
 * 
 * @param $name
 *   Textgroup and location glued with ':'.
 * @param $string
 *   Source string in default language. Default language may or may not be English.
 * @param $format
 *   Input format when the string is displayed through input formats
 */
function i18nstrings_update($name, $string, $format = NULL) {
  ....
}

The format parameter is to be used when the string is to be formatted with Input filters before displaying. If so, filter permissions will be properly handled by i18nstrings. Only users who can access the Input format will be able to translate those strings. These strings must be translated using i18nstrings_text() instead of i18nstrings().

3. (Optional) Refresh callback function as defined in hook_locale().

/**
 * Update / create translation source for user defined strings. 
 * 
 * @return $bool
 *   TRUE if update successful, FALSE if not.
 */
  function mymodule_locale_refresh() {
    ... 
    code to call i18nstrings_update() for every string used by this module
    ...
    return TRUE; // Update completed with no issues
  }

The refresh function should call i18nstrings_update() for every string that is to be translated in your module. The refresh interface will remove all strings defined by your module and only re-list the strings added by the refresh callback function.

Again, all Drupal core textgroups and strings will be defined and handled by i18nstrings when edited using the default pages for it. So you just need to implement these other functions when your module uses specific user-defined strings.

The easiest way to have the strings translated without adding a new module dependency is to create a wrapper for your module which just translates the strings when the i18nstrings module is enabled.

function mymodule_translate($name, $string, $langcode = NULL) {
  return function_exists('i18nstrings') ? i18nstrings($name, $string, $langcode) : $string;  
}

Or, if your module has its own textgroup, we can have a default parameter for that textgroup and same some code. Note we still keep the 'textgroup' parameter just in case we need to translate other module's strings, like for occasionally translating a taxonomy term or a content type name.

function mymodule_translate($name, $string, $langcode = NULL, $textgroup = 'mytextgroup') {
  return function_exists('i18nstrings') ? i18nstrings($textgroup . ':' . $name, $string, $langcode) : $string;  
}

Examples of modules implementing this wrapper are:

Comments

PROMES’s picture

It would be nice to give an example how to intrepret the comment in the function i18nstrings(). It states:
@param $name
* Textgroup and location glued with ':'.
but nowhere I can find what location means.
I studied the whole source and in the end I found out what is the meaning of location.
The location is the id you find under the string when seaching for a string in the translated strings.

So when I find in the translation string as id: "term:12:name" this is the "location" and the "name" is: "taxonomy:term:12:name" or in programming: "taxonomy:term:$vocab->tid:name".

But from the source I found "name" "taxonomy:term" should do it also ???

Please clarify when I should use what.

Daniel_KM’s picture

The name identifiant is the unique location id used by the database. Strings and translations are save in two tables, locales_source and locales_target, and the identifiant allows to make a link between them. Sometime, name is use for the whole string, sometime for a portion of it.

The location name or location id is composed of [textgroup]:[type]:[key]:[property]:

  • textgroup: generaly the name of the node or of the core module, here taxonomy
  • context: the other items of the location name
    • type: content type of the item to translate
    • key: the unique identifiant of the item
    • property: property of the item that have a translation ("name" or "description" for terms)

This id can sometime be a string (taxonomy:term:10:description), but can sometime be an array (array('taxonomy', 'term', 10, 'description')).

Sincerely,