Hi.

GIVEN
A taxonomy vocabulary with terms that has (many start with) a non-Latin character.
Drupal core taxonomy module correctly sort the terms ignoring the diacritics.
Facet API does not correctly sort the terms, as it list the ones that start with a non-Latin character in the end.

IN FACET BLOCK - INCORRECT
facet-not-sorted-correctly

IN DRUPAL CORE (admin/structure/taxonomy/VOCABULARY_NAME) - CORRECT
core-taxonomy-sorted-correctly

HELP
I was trying to delve into the code but could not find where the actual sorting happens.
Any help here?

Thanks,
Amir

Comments

Amir Simantov created an issue. See original summary.

fmfpereira’s picture

Same as here for all the facet types.

eugene.ilyin’s picture

Yes, it works great for taxonomy because there they are sorted through mysql.
But for facets values sorted by PHP. I don't see a good way to do it universally for all languages and cases. Also, it's pretty risky because it can lead to regressions on existing sites.

I propose the recipe, which consists of two steps:
1. use hook_facetapi_sort_info_alter and alter the callback for sorting
2. provide your own callback to sort facet values as you want

eugene.ilyin’s picture

Status: Active » Fixed
amir simantov’s picture

Hi Eugene,

Your explanation was very good - thanks for your time helping me figuring out how to do it, I appreciate it.

For documentation, I add here my code.

Here is the hook overriding where I map my callback function and the implementation of the callback function.

/**
 * Implements hook_facetapi_sort_info_alter().
 */
function facetapicustom_facetapi_sort_info_alter(array &$sort_info) {
	$sort_info['display']['callback'] = 'facetapicustom_sort_display';
}

// Copied and changed from module facetapi/plugins/facetapi/widget.inc
function facetapicustom_sort_display(array $a, array $b) {
	$a_display = (isset($a['#markup'])) ? $a['#markup'] : '';
	$b_display = (isset($b['#markup'])) ? $b['#markup'] : '';

	if ($a_display == $b_display) {
		return 0;
	}

	 $a_display = lib_string_remove_diacritics($a_display);
	 $b_display = lib_string_remove_diacritics($b_display);

	return strcasecmp($a_display, $b_display);
}

Here is a simple helper function that I have put in my custom library:

function lib_string_remove_diacritics($string) {
    return str_ireplace(
    	array('Ā', 'Ī', 'ṇ', 'Ṛ', 'Ś', 'ṣ', 'Ṭ'), 
    	array('A', 'I', 'N', 'R', 'S', 'S', 'T'), 
    	$string);
}

I would note that I did try to convert to different encoding but it was getting complicated, so a simple replacing of characters was easier.

Thanks again.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

nikolay shapovalov’s picture

As an idea, inspired by https://stackoverflow.com/questions/27187285/sorting-russian-english-list
You can transliterate values using https://www.drupal.org/project/transliteration and then sort them.