Collation and Sorting by Locale with Intl.Collator
Sort strings correctly for any language using Intl.Collator. Learn about sensitivity levels, numeric sorting, case-first options, and how sort order varies across locales.
Detailed Explanation
Intl.Collator: Locale-Aware String Sorting
Default JavaScript string comparison (localeCompare or < / >) does not handle locale-specific sorting rules correctly. Intl.Collator provides proper locale-aware string comparison.
Why Default Sort Fails
// Default sort puts uppercase first, ignores locale rules
['banana', 'Apple', 'cherry'].sort();
// ["Apple", "banana", "cherry"]
// German: ä should sort near 'a', not after 'z'
['äpfel', 'Apfel', 'Banane'].sort();
// ["Apfel", "Banane", "äpfel"] -- wrong!
Locale-Aware Sorting
const de = new Intl.Collator('de');
['äpfel', 'Apfel', 'Banane'].sort(de.compare);
// ["Apfel", "äpfel", "Banane"] -- correct!
const sv = new Intl.Collator('sv');
['äpple', 'apple', 'banana'].sort(sv.compare);
// ["apple", "banana", "äpple"]
// In Swedish, ä sorts AFTER z!
Sensitivity Levels
// "base": a = A = à = À
new Intl.Collator('en', { sensitivity: 'base' })
.compare('a', 'A'); // 0 (equal)
// "accent": a = A, à ≠ a
new Intl.Collator('en', { sensitivity: 'accent' })
.compare('a', 'à'); // not 0
// "case": a ≠ A, à = a
new Intl.Collator('en', { sensitivity: 'case' })
.compare('a', 'A'); // not 0
// "variant": a ≠ A ≠ à ≠ À
new Intl.Collator('en', { sensitivity: 'variant' })
.compare('a', 'à'); // not 0
Numeric Sorting
// Without numeric: "item10" < "item2" (string comparison)
// With numeric: "item2" < "item10" (number-aware)
const col = new Intl.Collator('en', { numeric: true });
['item10', 'item2', 'item1', 'item20'].sort(col.compare);
// ["item1", "item2", "item10", "item20"]
Case-First Option
// Upper-case first
new Intl.Collator('en', { caseFirst: 'upper' })
['apple', 'Apple', 'APPLE'].sort(col.compare);
// ["APPLE", "Apple", "apple"]
// Lower-case first
new Intl.Collator('en', { caseFirst: 'lower' })
['apple', 'Apple', 'APPLE'].sort(col.compare);
// ["apple", "Apple", "APPLE"]
Performance
Intl.Collator is significantly faster than String.prototype.localeCompare() for sorting large arrays because the collator is created once and reused:
// Slow: creates new collator per comparison
arr.sort((a, b) => a.localeCompare(b, 'de'));
// Fast: reuses single collator
const col = new Intl.Collator('de');
arr.sort(col.compare);
Use Case
Correct sorting is critical for directory listings, contact lists, search result ordering, and any alphabetical display. A German address book must sort names with umlauts correctly. A Swedish application must place characters like 'a' and 'ä' in the right order (they are different letters in Swedish). File managers need numeric sorting so 'file2' appears before 'file10'. Using Intl.Collator ensures strings are sorted according to the user's language expectations.
Try It — Locale String Tester
Related Topics
Intl.DisplayNames API: Language, Region, Script, and Currency Names
Intl.DisplayNames
List Formatting with Intl.ListFormat (And, Or, Unit)
Intl.ListFormat
Intl.NumberFormat Basics: Locale-Aware Number Formatting
Intl.NumberFormat
Locale Fallback Chain: How Browsers Resolve Locale Requests
Advanced
Plural Rules by Language with Intl.PluralRules
Intl.PluralRules