Dotless
A small library for matching names across languages without breaking Turkish ı and İ.
Context
Case conversion depends on locale. In Turkish, I lowercases to ı and i uppercases to İ, so a case-insensitive search for a city or a surname gives different answers depending on how the server was configured. Names with accents fail the other way: Şenyüz and Senyuz never match.
Idea
Make every step explicit and visible to the caller: Unicode normalization first, then a case fold for a locale the caller passes in, then an optional accent-free key for search. Each step is a pure function with its own tests, and nothing reads the locale from the environment.
| Row | Input | Locale | searchKey |
|---|---|---|---|
| 0000 | ŞENYÜZ | tr | senyuz |
| 0010 | Şenyüz | und | senyuz |
| 0020 | ISTANBUL | tr | ıstanbul |
| 0030 | ISTANBUL | en | istanbul |
| 0040 | İstanbul | tr | istanbul |
Details
Normalize first
Text is converted to NFC before anything else, so a ü typed as one code point and a ü built from u plus a combining mark compare as equal.
Locale is an argument
The library never guesses. A missing locale means the root locale, and the README shows why that matters with real names.
Tests from real failures
The test suite is a list of names that other libraries got wrong, each with the expected key. Bug reports become rows in that list.
export function searchKey(input: string, locale = 'und') { return input .normalize('NFC') .toLocaleLowerCase(locale) .normalize('NFD') .replace(/\p{Mn}/gu, '');} searchKey('ŞENYÜZ', 'tr'); // 'senyuz'searchKey('ISTANBUL', 'tr'); // 'ıstanbul'Outcome
Published as a package with a deliberately tiny API. The interesting part turned out to be the test list, which now doubles as documentation for anyone handling names.