Skip to content

Report the collations CLDR actually defines - #2989

Merged
lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix/collation-cldr-data
Aug 13, 2026
Merged

Report the collations CLDR actually defines#2989
lahma merged 1 commit into
sebastienros:mainfrom
lahma:fix/collation-cldr-data

Conversation

@lahma

@lahma lahma commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

The LocaleCollationSupport table diverged from CLDR, and #2974 made the divergence public through getCollations(). Every change carries its CLDR citation (common/bcp47/collation.xml deprecation status + per-locale common/collation/*.xml, ICU cross-checked at cldrVersion 49):

  • removed as deprecated: big5han/gb2312 (zh), direct (hi), reformed (sv — replaced by trad, which sv defines)
  • removed as undataed: ducet (en) — not deprecated, but no locale defines a ducet collation; the hi.xml grep hit is prose about DUCET order. CLDR beats node here: node omits both ducet and direct, but for different reasons, and the commit says which is which rather than lumping them.
  • added: trad for fi and vi (both define traditional); dict (si), trad (es) spelling fixes; ar drops a redundant root echo.

yue is deliberately absent, and there is a test pinning why. CLDR routes yue's collations to zh_Hant and node reports them — but Intl.Collator.supportedLocalesOf(['yue']) is [] here (available locales come from CultureInfo.GetCultures), so adding the row recreated the exact report-vs-accept disagreement #2974 closed, on one tag. Measured, backed out, and LocaleReportsOnlyTheRootCollationsForAnUnavailableLanguage now stops the row returning before the locale can.

The hand-kept DefaultCldrProvider.GetSupportedCollations() had to move in the same commit — leaving the five removed identifiers in it turns test262's collations-accepted-by-Collator.js red. The follow-up PR derives that list so it cannot drift again.

Red 16 / green 146, both TFMs. test262 standalone baseline-identical on a quiet machine.

🤖 Generated with Claude Code

sebastienros#2974 made Intl.Locale.prototype.getCollations and Intl.Collator agree on
whatever LocaleCollationSupport says, and left open whether what it says is
CLDR at all. It is not, in six places. The table is the one CLDR reads two
ways: common/bcp47/collation.xml registers the collation identifiers and marks
the dead ones deprecated, and common/collation/<language>.xml says which of
them a language actually defines.

    identifier   registry                    per-language file
    big5han      deprecated="true"           defined by no locale
    direct       deprecated="true"           defined by no locale
    gb2312       deprecated="true"           defined by no locale
    reformed     deprecated="true"           defined by no locale
    ducet        current                     defined by no locale

Those five were reachable. "ducet" is the one that is not deprecated - it is
registered and current, and CLDR simply ships no data for it, a search of
common/collation for a <collation type="ducet"> finding nothing and the hi.xml
hit being prose about the DUCET order rather than a type. Either way no
locale's file defines it, so no locale's [[co]] list may contain it. The other
four are deprecated and equally undefined; "reformed" in particular is the old
name for what sv.xml has called "traditional" for many releases.

What the per-language files say, minus the "standard" and "search" every one of
them carries and the "private-" types CLDR keeps only to be [import]ed:

    ar   compat                              unchanged
    de   search, phonebook, eor              unchanged as phonebk, eor
    en   (no <collations> element at all)    "ducet" removed, row now empty
    es   traditional                         unchanged as trad
    fi   traditional                         "trad" added, row is new
    hi   standard                            "direct" removed, row now empty
    ja   private-kana, unihan                unchanged
    ko   searchjl, unihan                    unchanged
    ln   phonetic                            unchanged
    si   dictionary                          unchanged as dict
    sv   traditional                         "reformed" replaced by "trad"
    vi   traditional                         "trad" added, row is new
    zh   private-pinyin, pinyin, stroke,     "big5han" and "gb2312" removed
         zhuyin, unihan

root.xml defines "standard", "search", "eor", "private-unihan" and "emoji", so
RootCollations stays ["emoji", "eor"] and every locale keeps getting it. That
is also why the en, hi and da rows go away entirely rather than shrinking: once
what CLDR does not support is gone, what is left of them is the root pair every
locale already gets, which is the same reason fr and tr never needed a row. The
rows that remain now say one thing - what this language adds - so the "eor"
that ar, es, ja, ko, ln, si, sv and zh used to repeat is gone from them too,
while de keeps its own, which de.xml really does define as a German delta on
the European ordering rules.

Intl.supportedValuesOf("collation") moves with them.
https://tc39.es/ecma402/#sec-availablecanonicalcollations wants the collations
the implementation provides Intl.Collator functionality for, and
intl402/Intl/supportedValuesOf/collations-accepted-by-Collator.js checks
exactly that against ten locales - so leaving the five in
DefaultCldrProvider.GetSupportedCollations while no locale resolves them any
more turns that test red on "big5han is supported by Collator". It is still a
third hardcoded list that can drift from the table; deriving it is a separate
change.

Left alone: yue, which CLDR does give zh's set. It has no collation file, and
supplementalData.xml's <parentLocales component="collations"> makes zh_Hant its
collation parent, whose file defines only a defaultCollation - which is why
node reports pinyin, stroke, unihan and zhuyin for it and ICU's coll/yue.txt is
a bare %%ALIAS to zh_Hant. Jint cannot report it yet: "yue" matches no element
of IntlUtilities.GetAvailableLocales(), so Intl.Collator.supportedLocalesOf
(['yue']) is empty and new Intl.Collator('yue') resolves to the default locale.
A row would have advertised four collations Intl.Collator answers "default" for
- the disagreement sebastienros#2974 removed, restored on one tag. Reporting them waits on
making yue an available Collator locale, and a test pins the current answer and
the reason so a later row cannot be added without it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@lahma
lahma force-pushed the fix/collation-cldr-data branch from 3ecdaa8 to d91412b Compare August 12, 2026 06:45
@lahma
lahma merged commit c04c94f into sebastienros:main Aug 13, 2026
5 checks passed
@lahma
lahma deleted the fix/collation-cldr-data branch August 13, 2026 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant