views formatter translation when using i18n with entity_translation should account for entity field translation

Created on 21 September 2017, almost 8 years ago
Updated 11 November 2023, almost 2 years ago

If you set a vocabulary to use the multilingual mode of Translate, which allows you to create different terms in each language and translate them, the allowed values function does not account for the case where the terms are only actually in English, but you have added translations of your terms using entity translation.

What happens is that i18n_taxonomy_get_tree() runs a DB query that tries to fetch terms where the language matches the current language. If you have used entity translation, then it will not find any terms in languages other than the default language normally. It needs, therefore, to have an additional check to see if no terms are found, then just load the terms the normal way. Then, it needs to be able to return the entity translated value if available.

What I did to fix this issue in my own case for the time being was write a custom module that overrides the options_list_callback on the field settings. In my own function, I simply had it load all terms the normal way and then use an entity metadata wrapper to set the option values using the label() function, which returns the translated name if applicable. This works for me since I know I'm always using the translate mode, never localise or others, for my translatable taxonomy terms in my particular site.

function i18n_taxonomy_select_options_allowed_values($field) {
  global $language;
  $options = array();
  foreach ($field['settings']['allowed_values'] as $tree) {
    if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {
      $terms = taxonomy_get_tree($vocabulary->vid, $tree['parent']);
      if ($terms) {
        foreach ($terms as $term) {
          $term = taxonomy_term_load($term->tid);
          $term_wrapper = entity_metadata_wrapper('taxonomy_term', $term);
          $options[$term->tid] = str_repeat('-', $term->depth) . $term_wrapper->label();
        }
      }
    }
  }
  return $options;
}

Note that there is a good reason for reloading the taxonomy term within the foreach. If I don't do that, I get an error about the taxonomy term not having a bundle when it tries to create the entity metadata wrapper. I don't know why the term object doesn't otherwise have all the data it's supposed to from taxonomy_get_tree() and I didn't spend much time looking into it. Reloading it solved the issue.

The problem should, however, be properly addressed in the i18n_taxonomy sub-module. I think what should happen is when it tries to load terms using i18n_taxonomy_get_tree, if the result of that is empty it should fall back on taxonomy_get_tree. That would ensure that worst case it falls back on populating the allowed values with ones in the default language, which is normally how you expect Drupal multilingual sites to behave. The i18n_taxonomy_term_name function then needs to always load the translated term name properly in the case that we're using this translation mode. The simplest way is with an entity metadata wrapper, because calling the label() function will automatically return it in the right language, if a translation exists, or fallback on the default language if a translation isn't found.

So, I might change i18n_taxonomy_allowed_values function to this:

function i18n_taxonomy_allowed_values($field) {
  global $language;
  $options = array();
  foreach ($field['settings']['allowed_values'] as $tree) {
    if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {
      if (i18n_taxonomy_vocabulary_mode($vocabulary->vid) == I18N_MODE_TRANSLATE) {
        $parent = i18n_taxonomy_translation_term_tid($tree['parent'], NULL, $tree['parent']);
        $language = i18n_language_context();
        $terms = i18n_taxonomy_get_tree($vocabulary->vid, $language->language, $parent);
        if (empty($terms)) {
          $terms = taxonomy_get_tree($vocabulary->vid, $tree['parent']);
        }
      }
      else {
        $terms = taxonomy_get_tree($vocabulary->vid, $tree['parent']);
      }
      if ($terms) {
        foreach ($terms as $term) {
          $options[$term->tid] = str_repeat('-', $term->depth) . i18n_taxonomy_term_name($term);
        }
      }
    }
  }
  return $options;
}

Then change i18n_taxonomy_term_name to the following:

function i18n_taxonomy_term_name($term, $langcode = NULL) {
  $key = i18n_object_info('taxonomy_term', 'key');
  if (i18n_taxonomy_vocabulary_mode($term->vid, I18N_MODE_LOCALIZE)) {
    return i18n_string(array('taxonomy', 'term', $term->{$key}, 'name'), $term->name, array('langcode' => $langcode, 'sanitize' => FALSE));
  }
  $wrapper = entity_metadata_wrapper('taxonomy_term', taxonomy_term_load($term->tid));
  return $wrapper->label();
}

Again it's reloading the taxonomy term using taxonomy_term_load to be safe for the same reason I did that in my own override function above. By always using the entity metadata wrapper to get the term label in all cases other than localise multilingual mode, we're safe. It will return a translated name if applicable, or the default language name otherwise.

🐛 Bug report
Status

Active

Version

1.34

Component

Fields

Created by

🇨🇦Canada teknocat

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024