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.