I need to compare Unicode strings in JavaScript while ignoring case differences. From what I understand, the correct approach should be using case folding before comparison, similar to how other languages handle this.
In Python, there’s a built-in method that works perfectly for this:
However, JavaScript doesn’t seem to have an equivalent built-in function. I tried using Intl.Collator but it doesn’t work correctly for all Unicode characters.
Here’s what I tested:
let stringA = "Café İstanbul ß"
let stringB = "café i̇stanbul ss"
let stringC = "cafe i̇stanbul ß"
// Using base sensitivity
let baseCollator = new Intl.Collator('en', { sensitivity: 'base' })
console.log(baseCollator.compare(stringA, stringB) === 0) // Works fine
console.log(baseCollator.compare(stringA, stringC) === 0) // Wrong result
// Using accent sensitivity
let accentCollator = new Intl.Collator('en', { sensitivity: 'accent' })
console.log(accentCollator.compare(stringA, stringB) === 0) // Wrong result
console.log(accentCollator.compare(stringA, stringC) === 0) // Works fine
The problem is that different sensitivity modes give different results, and none of them handle all Unicode cases correctly like Python’s casefold method does.
What’s the best way to implement proper case-insensitive Unicode string comparison in JavaScript? Are there any reliable libraries or native approaches I’m missing?
the normalize() + toLowerCase() combo doesn’t always work. I’ve tried lodash’s isEqual with preprocessing, but localeCompare() with proper locale settings beats Intl.Collator most of the time. try str1.localeCompare(str2, undefined, {sensitivity: 'base'}) - works well for turkish and german characters in my experience.
I had the same problem building search for international content. JavaScript’s Unicode handling is pretty weak - it doesn’t have proper case folding algorithms like other languages do.
I tested a bunch of approaches and found toLocaleLowerCase() with specific locales beats generic toLowerCase() most of the time. For Turkish, try str.toLocaleLowerCase('tr-TR') - Turkish has weird rules for İ and ı characters.
But if you’re dealing with multiple languages in production, I’d just use the unicode-case-folding library someone mentioned. It’s built to copy Python’s casefold behavior and handles tricky stuff like German ß correctly.
Basically, JavaScript’s string methods were made for basic ASCII. Modern apps need real Unicode case folding, which means external libraries or complex normalization that still misses some character combos.
Your issue comes from JavaScript’s weak Unicode normalization compared to Python’s casefold. I’ve hit this exact problem in a multilingual app where the usual methods kept failing.
Here’s what actually works: combine normalization with locale-aware comparison. Don’t just rely on Intl.Collator sensitivity settings. Normalize both strings with Unicode NFD first, then convert case:
If you’re dealing with tricky characters like German ß or Turkish İ, grab the unicode-case-folding npm package. It does proper Unicode case folding like Python’s casefold and catches edge cases that native JavaScript misses.
That Intl.Collator inconsistency happens because ‘base’ and ‘accent’ sensitivities handle different character types. Neither works reliably for true case-insensitive comparison across all Unicode ranges.