Lists with items containing non-ascii characters are not sorted correctly

Created on 12 May 2014, almost 11 years ago
Updated 15 January 2023, about 2 years ago

Many efforts have been made to make Drupal 8 a great multilingual system. However, content types are never properly sorted when translations contain accentuated characters.

Content types are sorted using asort. Maybe we could set the locale beforehand.

Steps to reproduce:

Install Drupal 8
Enable the following modules

  • Configuration Translation
  • Content Translation
  • Interface Translation
  • Language

Add a language (French in the example)
Add a two content types (Show and Zone)
Translate the Show content type to Émission
Switch languages (fr/admin/structure/types)

Expected behavior

To have a list in this order

  • Article
  • Basic page
  • Émission
  • Zone

What happened instead

List was in this order:

  • Article
  • Basic page
  • Zone
  • Émission
🐛 Bug report
Status

Needs review

Version

10.1

Component
Language system 

Last updated 2 days ago

  • Maintained by
  • 🇩🇪Germany @sun
Created by

🇨🇦Canada nlambert

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Status changed to RTBC about 2 years ago
  • 🇮🇳India ameymudras

    Tested on 10.1.x and following is my observation

    1. The issue summary is clear and explains the overall problem
    2. Testing steps have been provided and was able to reproduce the issue
    3. Patch #24 applies cleanly and the non-ASCII config entity sort correctly
    4. Tests have been included and passes for #24
    5. Did code review and no issues were identified

    Marking this as RTBC, not including additional screenshots. Already provided in #27

  • Status changed to Needs review about 2 years ago
  • 🇬🇧United Kingdom longwave UK
    +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php
    @@ -226,14 +226,22 @@ public function createDuplicate() {
    +      $language_id = \Drupal::service('language_manager')
    ...
    +      $a_label = \Drupal::service('transliteration')->transliterate(
    ...
    +      $b_label = \Drupal::service('transliteration')->transliterate(
    

    A bit concerned about calling all these services inside the sort callback, because it feels like this is not going to be very performant in a case when there are hundreds of items or more to sort.

    We could at least extract the transliteration service to a variable, and also skip transliterating the empty string if it is falsy? Is there a way of injecting at least the language ID, given that it never changes, or the transliteration service itself?

    Also, do we have the same concerns about sorting in different languages as was raised in #3262017-90: Country list is not correctly sorted when it's localized with accents (e.g. German, Turkish) ? Is transliterating the right thing to do in all cases?

  • Status changed to Needs work about 2 years ago
  • Status changed to Needs review about 2 years ago
  • 🇩🇪Germany sleitner

    @longwave : I remove transliteration and added the Collator like in 🐛 Country list is not correctly sorted when it's localized with accents (e.g. German, Turkish) Postponed .

  • 🇩🇪Germany sleitner

    To prevent MethodArgumentValueNotImplemented exception in Collator, language_id en is used if intl extension is not installed.

  • 🇬🇧United Kingdom longwave UK

    The new polyfill and intl extension have the same considerations as 🐛 Country list is not correctly sorted when it's localized with accents (e.g. German, Turkish) Postponed so this will need to wait for the decision over there first.

  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update almost 2 years ago
    29,277 pass, 2 fail
  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update almost 2 years ago
    29,300 pass
  • Status changed to Postponed almost 2 years ago
  • 🇺🇸United States smustgrave

    Also posted to the #needs-review-queue-initative slack channel so hopefully a framework manager can take a look at that one.

  • Open in Jenkins → Open on Drupal.org →
    Environment: PHP 8.1 & MySQL 5.7
    last update almost 2 years ago
    Patch Failed to Apply
  • Status changed to Needs work about 1 year ago
  • 🇩🇪Germany sleitner

    Unpostpone it. 🐛 Country list is not correctly sorted when it's localized with accents (e.g. German, Turkish) Postponed is postponed because nobody wants to break the API.

  • Pipeline finished with Failed
    about 1 year ago
    Total: 172s
    #109189
  • Pipeline finished with Failed
    about 1 year ago
    Total: 178s
    #109190
  • Pipeline finished with Failed
    about 1 year ago
    #109196
  • Pipeline finished with Failed
    about 1 year ago
    Total: 553s
    #109197
  • Pipeline finished with Failed
    about 1 year ago
    #109205
  • Pipeline finished with Canceled
    about 1 year ago
    Total: 491s
    #109219
  • Pipeline finished with Failed
    about 1 year ago
    Total: 487s
    #109228
  • Pipeline finished with Failed
    about 1 year ago
    Total: 483s
    #109240
  • Pipeline finished with Failed
    about 1 year ago
    #109257
  • Pipeline finished with Failed
    about 1 year ago
    Total: 479s
    #109260
  • Pipeline finished with Failed
    about 1 year ago
    Total: 183s
    #109281
  • Pipeline finished with Running
    about 1 year ago
    #109285
  • Status changed to Needs review about 1 year ago
  • 🇩🇪Germany sleitner

    Converted to MR

  • Status changed to Needs work about 1 year ago
  • 🇺🇸United States smustgrave

    Can the issue summary be updated to use the standard template please.

    Hiding all patches for clarity as fix is in MR now.

    Will need framework manager review for the package being added.

  • Status changed to Needs review 11 months ago
  • Status changed to Needs work 11 months ago
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • Pipeline finished with Failed
    11 months ago
    Total: 134s
    #178482
  • Pipeline finished with Success
    10 months ago
    Total: 180s
    #191129
  • Pipeline finished with Failed
    10 months ago
    Total: 338s
    #191128
  • Pipeline finished with Failed
    10 months ago
    #191123
  • Pipeline finished with Failed
    10 months ago
    Total: 504s
    #191422
  • Pipeline finished with Failed
    10 months ago
    Total: 553s
    #191438
  • Pipeline finished with Success
    10 months ago
    Total: 512s
    #191445
  • Status changed to Needs review 10 months ago
  • Status changed to Needs work 10 months ago
  • 🇺🇸United States smustgrave

    Took a look at the MR before pinging a framework manager and seems we are updating several packages that seem unrelated to this. Can those be reverted please.

  • Pipeline finished with Success
    10 months ago
    Total: 512s
    #195761
  • Pipeline finished with Success
    10 months ago
    Total: 537s
    #195792
  • Status changed to Needs review 10 months ago
  • Status changed to Needs work 10 months ago
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • Pipeline finished with Success
    10 months ago
    Total: 619s
    #199928
  • Status changed to Needs review 10 months ago
  • 🇩🇪Germany sleitner

    Rerolled again

  • Status changed to RTBC 10 months ago
  • 🇺🇸United States smustgrave

    I can't make the call about the new package but the MR does fix the problem described in the issue summary. Moving to RTBC to put in front of the framework managers.

  • Status changed to Needs work 9 months ago
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • Pipeline finished with Canceled
    9 months ago
    Total: 63s
    #221033
  • Pipeline finished with Failed
    9 months ago
    Total: 458s
    #221034
  • Pipeline finished with Success
    9 months ago
    Total: 502s
    #221056
  • Status changed to RTBC 9 months ago
  • 🇩🇪Germany sleitner

    Rerolled again

  • Status changed to Needs work 9 months ago
  • 🇬🇧United Kingdom catch

    It's fine to add a new Symfony polyfill, (more a release management decision than a framework one) but there should really be a dependency evaluation in the issue summary here per https://www.drupal.org/about/core/policies/core-dependency-policies/depe... - can be very short because we know the answers in this case.

  • Status changed to Needs review 9 months ago
  • 🇩🇪Germany sleitner

    Dependency evaluation added to issue summary

  • Status changed to Needs work 9 months ago
  • The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

    This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

    Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

  • Status changed to Needs review 9 months ago
  • Status changed to RTBC 9 months ago
  • 🇺🇸United States smustgrave

    Remarking as dependency eval has been added to summary.

  • 🇳🇿New Zealand quietone

    I read the IS, comments and the MR. The only possible thing to consider is @longwave's point in #31 about calling services inside the sort callback "is not going to be very performant in a case when there are hundreds of items or more to sort". The transliteration service was removed from an earlier iteration of the MR but is still is getting the LanguageManager.

    Leaving at RTBC.

  • Status changed to Needs work 6 months ago
  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    #31 still to be addressed.
    MR no longer applies in the meantime.

  • Pipeline finished with Canceled
    6 months ago
    Total: 349s
    #316419
  • Pipeline finished with Failed
    6 months ago
    #316424
  • Pipeline finished with Failed
    6 months ago
    Total: 190s
    #316435
  • Pipeline finished with Failed
    6 months ago
    Total: 167s
    #316439
  • Pipeline finished with Failed
    6 months ago
    Total: 284s
    #317325
  • Pipeline finished with Failed
    6 months ago
    Total: 124s
    #317366
  • Pipeline finished with Failed
    6 months ago
    Total: 330s
    #317374
  • Pipeline finished with Failed
    6 months ago
    Total: 187s
    #317383
  • Pipeline finished with Failed
    6 months ago
    Total: 330s
    #317385
  • Pipeline finished with Failed
    6 months ago
    Total: 475s
    #317392
  • Pipeline finished with Failed
    6 months ago
    Total: 233s
    #317405
  • Pipeline finished with Failed
    6 months ago
    Total: 171s
    #317417
  • Pipeline finished with Failed
    6 months ago
    Total: 741s
    #317513
  • Pipeline finished with Failed
    6 months ago
    Total: 154s
    #317548
  • Pipeline finished with Failed
    6 months ago
    Total: 163s
    #317565
  • Pipeline finished with Failed
    6 months ago
    Total: 542s
    #317567
  • Pipeline finished with Canceled
    6 months ago
    Total: 672s
    #317590
  • Pipeline finished with Success
    6 months ago
    Total: 391s
    #317595
  • Pipeline finished with Failed
    6 months ago
    Total: 790s
    #317600
  • Pipeline finished with Failed
    6 months ago
    Total: 322s
    #317612
  • Pipeline finished with Failed
    6 months ago
    Total: 130s
    #317614
  • Pipeline finished with Failed
    6 months ago
    #317618
  • Pipeline finished with Failed
    6 months ago
    Total: 673s
    #317624
  • Pipeline finished with Failed
    6 months ago
    Total: 684s
    #317662
  • Pipeline finished with Failed
    6 months ago
    Total: 186s
    #317671
  • Pipeline finished with Failed
    6 months ago
    Total: 200s
    #317673
  • Pipeline finished with Failed
    6 months ago
    Total: 203s
    #317677
  • Pipeline finished with Failed
    6 months ago
    Total: 204s
    #317679
  • Pipeline finished with Failed
    6 months ago
    Total: 638s
    #317682
  • Pipeline finished with Failed
    6 months ago
    Total: 636s
    #317690
  • Pipeline finished with Success
    6 months ago
    Total: 1029s
    #318009
  • 🇩🇪Germany sleitner

    The service is moved to a new function

    public static function sortEntities(array &$entities): bool
    

    which calls a new compare function public static function compare(ConfigEntityInterface $a, ConfigEntityInterface $b, \Collator $collator): int.
    The sort functionpublic static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) is now deprecated in all child classes.

  • 🇺🇸United States smustgrave

    appears to have merge conflict but the tag no-needs-review-bot kept the bot from getting it.

  • Pipeline finished with Canceled
    5 months ago
    Total: 74s
    #327857
  • Pipeline finished with Failed
    5 months ago
    Total: 599s
    #327859
  • Pipeline finished with Success
    5 months ago
    Total: 747s
    #327880
  • 🇩🇪Germany sleitner

    Rerolled

  • Pipeline finished with Failed
    3 months ago
    Total: 136s
    #387654
  • Pipeline finished with Failed
    3 months ago
    Total: 445s
    #387660
  • Pipeline finished with Canceled
    3 months ago
    Total: 627s
    #387668
  • Pipeline finished with Failed
    3 months ago
    Total: 83s
    #387679
  • Pipeline finished with Success
    3 months ago
    Total: 625s
    #387680
  • 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10

    Left a review on the MR
    Would it be simpler (less re-rolls etc) to get the new dependency in first in a separate issue?

  • Pipeline finished with Failed
    3 months ago
    Total: 506s
    #396079
  • Pipeline finished with Canceled
    3 months ago
    Total: 127s
    #396092
  • Pipeline finished with Success
    3 months ago
    Total: 459s
    #396094
  • 🇩🇪Germany sleitner

    @larowlan all references to 11.1 are replaced by 11.2

  • Pipeline finished with Failed
    3 months ago
    Total: 539s
    #400297
  • Pipeline finished with Success
    2 months ago
    Total: 924s
    #410224
  • 🇺🇸United States smustgrave

    Feedback appears to be addressed.

  • 🇬🇧United Kingdom longwave UK

    Do we need to deprecate sort()? Can we add the Collator as an optional argument to the existing method, and trigger a deprecation if it's not passed in?

  • 🇬🇧United Kingdom longwave UK

    Also there is a merge conflict, some out of scope changes in composer.json/lock.

  • Pipeline finished with Failed
    2 months ago
    Total: 580s
    #418085
  • Pipeline finished with Failed
    2 months ago
    Total: 88s
    #418099
  • Pipeline finished with Failed
    2 months ago
    Total: 482s
    #418112
  • Pipeline finished with Success
    2 months ago
    Total: 2942s
    #418124
  • 🇩🇪Germany sleitner

    @longwave you pointed in #31 about calling services inside the sort callback "is not going to be very performant in a case when there are hundreds of items or more to sort". The solution is to place the service outside the compare function sort().

    Furthermore the function sort() name does not reflect its function. It is just comparing the two values, it is not sorting anything.

    The merge conflict is resolved.

  • 🇺🇸United States smustgrave

    @longwave going to go on a limb and say this is good. The lock file seems to only show the new dependency I believe.

  • Pipeline finished with Failed
    about 2 months ago
    Total: 611s
    #423241
  • Pipeline finished with Failed
    about 1 month ago
    Total: 1209s
    #443560
  • Pipeline finished with Success
    about 1 month ago
    Total: 788s
    #443584
  • Pipeline finished with Failed
    23 days ago
    Total: 242s
    #454011
  • Pipeline finished with Failed
    23 days ago
    Total: 123s
    #454019
  • Pipeline finished with Success
    23 days ago
    Total: 602s
    #454020
  • Status changed to RTBC 23 days ago
  • 🇩🇪Germany sleitner

    Rerolled

  • 🇬🇧United Kingdom catch

    Unfortunately this needs another rebase, the MR looks good to me.

  • Pipeline finished with Success
    13 days ago
    Total: 415s
    #461495
  • 🇩🇪Germany sleitner

    Rebased. What else needs to be done before the merge?

    • catch committed 0576f60c on 11.x
      Issue #2265487 by sleitner, tanuj., longwave, nlambert, larowlan,...
  • 🇬🇧United Kingdom catch

    I don't think there's anything left to do here, RTBC queue has been very busy (hard to keep under 100 issues even with over 100 commits/month and many more reviews).

    Committed/pushed to 11.x, thanks!

  • 🇦🇺Australia acbramley

    This blows up sites that don't have the intl extension

    adam@8fa2a3a71304:data $ drush cr
    PHP Fatal error:  Uncaught Error: Class "Collator" not found in /data/app/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php:239
    

    I think the intention of this code was to check the extension was loaded before initialising the $collator but I can't quite follow:

    $collator = \Collator::create((!extension_loaded('intl')) ? ('en') : (\Drupal::service('language_manager')->getCurrentLanguage()->getId()));
    
  • 🇦🇺Australia acbramley

    ::compare requires a Collator to be passed to it as well so we'll need to allow that the handle it being NULL?

    I missed the symfony polyfill in the MR though which does look like it works

  • 🇬🇧United Kingdom catch

    Just seen 🐛 Symfony\Polyfill\Intl\Icu\Collator::compare() is not implemented Active let's revert this and recommit with that fixed.

    • catch committed 4e9d819e on 11.x
      Revert "Issue #2265487 by sleitner, tanuj., longwave, nlambert, larowlan...
  • 🇬🇧United Kingdom catch

    Reverted the commit and marked 🐛 Symfony\Polyfill\Intl\Icu\Collator::compare() is not implemented Active as duplicate. Let's fix that here and re-commit.

    I think we should also open an upstream bug report against Symfony to implement the method, then we wouldn't need the checks added by that MR and could go back to the original code committed here.

  • 🇬🇧United Kingdom catch
  • Pipeline finished with Success
    12 days ago
    Total: 689s
    #462386
  • 🇩🇪Germany sleitner

    Fixed the problem in MR11697 and tested it here in tugboat. Please review.

  • Pipeline finished with Failed
    10 days ago
    #464303
  • Pipeline finished with Failed
    10 days ago
    #464311
  • Pipeline finished with Failed
    10 days ago
    #464312
  • Pipeline finished with Failed
    10 days ago
    #464313
  • Pipeline finished with Failed
    10 days ago
    #464323
  • Pipeline finished with Success
    10 days ago
    #464335
  • 🇩🇪Germany sleitner

    @acbramley : Test manually or automatically? Manually: "View live preview" via Tugboat next to the MR on the top of this issue page. In the tugboat PHP intl extension is not installed, at the moment. Same in Simplytest.me

  • Pipeline finished with Running
    10 days ago
    #464360
  • Pipeline finished with Success
    10 days ago
    #464375
  • 🇦🇺Australia acbramley

    Test manually or automatically

    I meant in automated tests, i.e to catch the bug that caused this to be reverted

  • 🇪🇸Spain penyaskito Seville 💃, Spain 🇪🇸, UTC+2 🇪🇺

    NW per the test. Also not sure why changing the API is necessary here.

  • Pipeline finished with Success
    3 days ago
    Total: 363s
    #470267
Production build 0.71.5 2024