Index localized taxonomy term with Search API and Solr

Soumis par GoZ le mar 14/02/2017 - 15:30

Index localized taxonomy term with Search API and Solr

In Drupal 7 with Search API and Solr, i need to index taxonomy terms label which are localized, so terms can be searched in full text or thanks to facets in each localized translation.

I use modules search_api, search_api_solr, search_api_et, search_api_et_solr and i18n_taxonomy.

I see many issues and patch to make this fixing or altering facets, but it's not the way here. I have an item by language and want to index the text for this language.

To make this possible, i alter documents thanks to hook_search_api_solr_documents_alter().
This code is not the best i can produce but i have no time to make it more generic and submit it as patch, so here is the snippet.

 * Implements hook_search_api_solr_documents_alter().
 * Taxonomy term names are not translated, even if they are configured as
 * localised. We have to force during indexation to be available by searches and
 * facets.
function MYMODULE_search_api_solr_documents_alter(&$documents, $index, $items) {
  // Run this only for multilingual indexes provided by search_api_et module.
  $controller = search_api_get_datasource_controller($index->item_type);
  if ($controller instanceof SearchApiEtDatasourceController) {

    foreach ($documents as $delta => $document) {
      // Get the current document language.
      $document_language_field = $document->getField('ss_search_api_language');
      $document_language = $document_language_field['value'];

      foreach ($document->getFieldNames() as $solr_field_name) {
        if (strpos($solr_field_name, '_') !== FALSE) {
          list($solr_prefix, $field_name) = explode('_', $solr_field_name, 2);

          // If last part is 'name', assume we deal with a taxonomy term field
          // name. Try to translate it.
          $field_name_parts = explode('$', $field_name);
          $last_part = array_pop($field_name_parts);
          if ($last_part == 'name') {
            // Find tid for this terms field. Tid are needed to translate term
            // with context.
            $solr_taxonomy_prefix = '';
            // Define prefix for string.
            if ($solr_prefix == 'ss') {
              $solr_taxonomy_prefix = 'is';
            // Define prefix for list.
            elseif ($solr_prefix == 'sm') {
              $solr_taxonomy_prefix = 'im';
            $taxonomy_term_field_name = $solr_taxonomy_prefix . '_' . implode('$', $field_name_parts);

            if ($taxonomy_term_field = $document->getField($taxonomy_term_field_name)) {

              // Get original value.
              $taxonomy_term_field_translated = $document->getField($solr_field_name);

              // Translate every terms name depending of textgroup and context.
              // In case no translation is available, default string will be
              // returned, so nothing to carry about this point.
              if (is_array($taxonomy_term_field_translated['value'])) {
                foreach ($taxonomy_term_field_translated['value'] as $key => $name) {
                  $context = 'term:' . $taxonomy_term_field['value'][$key] . ':name';
                  $taxonomy_term_field_translated['value'][$key] = i18n_string_translate('taxonomy:' . $context, $name, array('langcode' => $document_language));
              else {
                $context = 'term:' . $taxonomy_term_field['value'] . ':name';
                $taxonomy_term_field_translated['value'] = i18n_string_translate('taxonomy:' . $context, $taxonomy_term_field_translated['value'], array('langcode' => $document_language));

              // Override field value with translated name.
              $document->setField($solr_field_name, $taxonomy_term_field_translated['value'], $taxonomy_term_field_translated['boost']);

An improvement could be to load informations about current field, to check if it make reference to a taxonomy term field and finally check if translation config of vocabulary is setted to i18N_MODE.
Doing this without take care of performance could be bad, so some static methods uses to define which field is taxonomy and localized could be a good thing for large indexation.