Mugo Web main content.

"Sort by language" filter in eZ Publish

By: Peter Keung | November 21, 2014 | eZ Publish development tips

Multi-language sites often have a set of base rules and then edge cases for different parts of the site. For example, on the French version of the site you might only want to show French content on most pages. For the news section, you might want to show press release results from all languages sorted in reverse chronological order, regardless of language. But for the case study section specifically, you might want to show all French versions first, following by case studies in any other language. For the most part, eZ Publish supports these features out of the box. In this post, we'll show you how to extend eZ Publish to sort results by language.

Using the prioritized language list settings and some main language settings, you can configure which languages should show up on a per-site and a per-page basis.

A missing multi-language feature when fetching content is the ability to sort by languages. Thankfully, this can be accomplished using one of my favourite eZ Publish features: extended attribute filters.

The example extended attribute filter below presumes that you want to show English results first on the English site. For non-English sites, you want to show that language first, then English results, then all other languages.

<?php
/*
 * Adds the ability to sort results by language
 * On non-English sites, return results for the main language, then 
 * Use like so in a content/list or content/tree fetch only:
 * template example:
 * 'sort_by', array( array( 'language_priority', true() ), array( 'name', true() ) ),
 *                                                  'extended_attribute_filter', hash( 'id', 'SortByLanguageFilter'
 *                                                                                    ,'params', array()
 *                                                                                   ),
 * PHP example:
 * 'sort_by' => array( array( 'language_priority', true ), array( 'name', true ) ),
 * 'extended_attribute_filter' => array( 'id' => 'SortByLanguageFilter', 'params' => array() ),
*/
class SortByLanguageFilter
{
    function __construct()
    {
    }
 
    function createSqlParts( $params )
    {
        $ini = eZINI::instance();
        $prioritizedLanguageList = $ini->variable( 'RegionalSettings', 'SiteLanguageList' );

        $firstLanguage = $prioritizedLanguageList[0];

        // A standard content/list or content/tree fetch already grabs ezcontentobject_name
        $columns = ', CASE';

        // On an English site you're only going to get English results
        $columns .= " WHEN ezcontentobject_name.real_translation = '$firstLanguage' THEN 0";
        if( $firstLanguage == 'eng-US' )
        {
            $columns .= ' ELSE 1';
        }
        else
        {
            $columns .= " WHEN ezcontentobject_name.real_translation = 'eng-US' THEN 1 ELSE 2";
        }

        $columns .= ' END AS language_priority';

        return array( 'columns' => $columns, 'tables' => '', 'joins' => '' );
    }
}
?>

Probably the most important piece of code is the use of the CASE operator in MySQL. This enables you to set the language sort priorities for each fetch that is made. You can of course extend this further in order to support a longer list of language priority rules for sorting.

Follow the instructions from this other post in order to install the extended attribute filter.

Once you've installed the "sort by language" filter you can use a new sort method called "language_priority" like this (which sorts by language and then in reverse chronological order):

{def $case_studies = fetch( 'content', 'list',
            'parent_node_id', 888
           ,'limit', 10
           ,'sort_by', array( array( 'language_priority', true() ), array( 'published', false() ) )
           ,'extended_attribute_filter', hash( 'id', 'SortByLanguageFilter', 'params', array() )
)}