Sorting in a multi-language context when a client can add their own languages

I built a multi-language site that has a Glossary page. On the English page the entries are alphabetised:

There was an issue with Alphabetising Chinese so I used a simple check to turn of Alphabetisation when non-latin characters are detected in the page title:

  <?php if(ctype_alpha($page->title()->toString())): ?>

However, this is picking up the diacritics of Polish an non-latin. The client is now asking if they can have alphabetisation in Polish but characters like ‘Ł’ are not being sorting (they want it near L, whatever I try it’s being sorted at the end).

I’ve read about setting the locale via the config, but I’d have to do this manually and the client needs to option to have new languages themselves via the panel. I’m a bit stumped on how to tackle this one, what would be the best approach? I tried setting the locale like this:

  setlocale(LC_ALL, $kirby->language()->locale(LC_ALL));

But it doesn’t work. Any ideas?

Setting the locale separately shouldn’t be necessary, the locale is set in the language config files.

However, I found that even the sorting flag on sortBy() doesn’t work properly for the Polish language ( $projects = $page->children()->listed()->sortBy('title', 'asc', SORT_LOCALE_STRING);), not does even a simple array sort with the sorting flag

$titles = $projects->pluck('title', ',');
asort($titles, SORT_LOCALE_STRING);
dump($titles);

I googled a bit and found this:

$titles = $projects->pluck('title', ',');
$coll = collator_create($kirby->language()->locale()[0]); 
collator_asort($coll, $titles);
dump($titles);

which seems to sort the titles correctly.

Thanks! This works great when plucking the titles, but I need to return a page object to get the URL:

    <?php
    $alphabetise = $page->children()->listed();
    $coll = collator_create($kirby->language()->locale()[0]); 
    collator_asort($coll, $alphabetise); // doesn't work because $alphabetise is not an array
    ?>
    <ul class="glossary__terms">
    <?php foreach($alphabetise as $item): ?>
      <li>
        <a href="<?= $item->url()?>"><?= $item->title()?></a>
      </li>
    <?php endforeach ?>
    </ul>
  

I thought about sorting titles and urls into two separate arrays but they wouldn’t be in the same order after collator_asort

Yes, I’m aware of that.

Unfortunately, I have no idea whatsoever, why the sorting doesn’t work properly with the sort flag set (not even in basic PHP).

So why I posted my findings was to find a workaround, i.e. using the collator result for custom sorting via mapping of the collection, similar to what I did in this cookbook recipe:

This may be crude, but sorting the titles into an array then finding the page by title in the loop seems to work…

    <?php
    $alphabetise = $page->children()->listed()->pluck('title',',');
    $coll = collator_create($kirby->language()->locale()[0]); 
    collator_asort($coll, $alphabetise);
    ?>
    <ul class="glossary__terms">
    <?php foreach($alphabetise as $item):
    $target = $page->children()->listed()->findBy('title',$item)
    ?>
      <li>
        <a class="arrow-link" href="<?= $target->url()?>"><?= $target->title()?></a>
      </li>
    <?php endforeach ?>

This seems to work for the Chinese version of the page too, and I have no idea how Chinese sorting works! Thanks for pointing me in the right direction @texnixe , you’re the best!

1 Like