How to associate programatically the translation of new term to the original existing term? I've terms which share the same id in stored in field and I'd like to associate translation between them, so they're grouped on the same page at /taxonomy/term/%/translate

So I've existing original English term, then I'm creating manually term with different language, so I'm expecting this term to associate with the original one.

Not sure which hook would be the best, or it doesn't matter:


hook_taxonomy_term_presave
hook_taxonomy_term_insert


So in example I've:

/**
 * Implements hook_taxonomy_term_presave().
 */
function foo_taxonomy_term_presave($term) {
  $bundle = 'countries'; // Example bundle name
  $vid = ($voc = taxonomy_vocabulary_machine_name_load($bundle)) ? $voc-&gt;vid : NULL;
  if ($term-&gt;vid == $vid &amp;&amp; module_exists('i18n_string') &amp;&amp; $term-&gt;language &lt;&gt; 'en') {

    if ($shared_id = $term-&gt;field_shared_id[key($term-&gt;field_shared_id)][0]['value']) {

      // Find term which points to the same country, but in English
      $query = new EntityFieldQuery();
      $org_term_res = $query
        -&gt;entityCondition('entity_type', 'taxonomy_term')
        -&gt;entityCondition('bundle', $bundle)
        -&gt;propertyCondition('vid', $vid)
        -&gt;fieldCondition('field_shared_id', 'value', $shared_id, '=')
        -&gt;propertyCondition('language', 'en')
        -&gt;execute();

      // Load term in the main language
      if ($org_term = taxonomy_term_load(reset(reset($org_term_res))-&gt;tid)) {
        // If original term is loaded, continue translation
        $langcode = $term-&gt;language;
        $key = i18n_object_info('taxonomy_term', 'key');

        $result_translation = i18n_string_translation_update(
          array('taxonomy', 'term', $term-&gt;{$key}, 'name'), // Array or string concatenated with ':' that contains textgroup and string context where to store source and translation.
          $term-&gt;name,      // Translation string for this language code.
          $langcode,        // The language code to translate to a language other than what is used to display the page.
          $org_term-&gt;name   // Optional source string, just in case it needs to be created.
        );
        watchdog('foo', "Added !source translation: !translated in !lang (key: !key)", array('!source' =&gt; $org_term-&gt;name, '!translated' =&gt; $term-&gt;name, '!lang' =&gt; $term-&gt;language, '!key' =&gt; $term-&gt;{$key}), WATCHDOG_NOTICE);

      } // end: if

      i18n_string_object_update('taxonomy_term', $term); // not sure if it's needed for something

    } // end: if
  } // end: if

}


So the main translate part is in i18n_string_translation_update().
But it simply doesn't work as expected. The $result_translation returns the right data, but the association is not visible in UI at taxonomy/term/%/translate

There is no much documentation about it apart of Using the i18n API from other modules

So I'm using the right function in the right way?

Related:

how to get the translated taxonomy term programmatically?
Here is the function which takes $term as current term and $org_term which is original/source term.

&lt;?php
/**
 * Custom function to add term translations.
 */
function foo_add_term_translation($term, $org_term) {
  if ($org_term-&gt;i18n_tsid) {
    // Already part of a set, grab that set.
    $i18n_tsid = $org_term-&gt;i18n_tsid;
    $translation_set = i18n_translation_set_load($org_term-&gt;i18n_tsid);
    $translation_set-&gt;add_item($term);
    $translation_set-&gt;save_translations();
    watchdog('foo', "Added !source translation: !translated in !lang.", array('!source' =&gt; $org_term-&gt;name, '!translated' =&gt; $term-&gt;name, '!lang' =&gt; $term-&gt;language), WATCHDOG_NOTICE);
  }
  else {
    // We have no translation source nid, this could be a new set.
  }
}   


More code examples you'll find in i18n_translation module. 

This could be called either during insert or update as below:

/**
 * Implements hook_taxonomy_term_insert().
 */
function foo_taxonomy_term_insert($term) {
  foo_add_term_translation_wrapper($term);
}

/**
 * Implements hook_taxonomy_term_update().
 */
function foo_taxonomy_term_update($term) {
  foo_add_term_translation_wrapper($term);
}


Here is helpful wrapper function with example to load the original term where two terms share the same field value:

/**
 * Custom wrapper to update term translation.
 */
function foo_add_term_translation_wrapper($term) {

  $bundle = 'countries'; // Example bundle name
  $vid = ($voc = taxonomy_vocabulary_machine_name_load($bundle)) ? $voc-&gt;vid : NULL;
  if ($term-&gt;vid == $vid &amp;&amp; module_exists('i18n_taxonomy') &amp;&amp; $term-&gt;language &lt;&gt; 'en' &amp;&amp; empty($term-&gt;translation_set)) {

    if ($shared_id = $term-&gt;field_shared_id[key($term-&gt;field_shared_id)][0]['value']) {

      // Find term which points to the same country, but in English
      $query = new EntityFieldQuery();
      $org_term_res = $query
        -&gt;entityCondition('entity_type', 'taxonomy_term')
        -&gt;entityCondition('bundle', $bundle)
        -&gt;propertyCondition('vid', $vid)
        -&gt;fieldCondition('field_shared_id', 'value', $shared_id, '=')
        -&gt;propertyCondition('language', 'en')
        -&gt;execute();

      // Load term in the main language
      if ($org_term = taxonomy_term_load(reset(reset($org_term_res))-&gt;tid)) {
        foo_add_term_translation($term, $org_term);    
      } // end: if

    } // end: if
  } // end: if

}


See also:

https://drupal.org/node/2102933