npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

trtext

v0.1.1

Published

Turkish-correct lowercase, uppercase, folding, slugs and alphabet sorting. Zero dependencies, no ICU required.

Readme

trtext

npm version npm downloads CI license zero dependencies

Turkish-correct string operations for JavaScript and TypeScript. Zero dependencies, no ICU data required, pure functions only.

The problem

String.prototype.toLowerCase() is deliberately locale-independent, so it is wrong for Turkish:

"I".toLowerCase() // "i"  — should be "ı"
"İ".toLowerCase() // "i̇" — an "i" plus a combining dot above, length 2
"i".toUpperCase() // "I"  — should be "İ"

This is the Turkish locale bug, and it keeps resurfacing: it has hit the Kotlin compiler, Gradle and Vaadin, among many others. The usual symptom is an identifier, class name, file extension or user login that silently stops matching on a Turkish machine.

What about toLocaleLowerCase("tr")?

It works, and you should use it when you can. On a runtime that ships Turkish ICU data it is correct, including the awkward cases:

"İ".toLocaleLowerCase("tr") // "i" — one character, no combining dot
"ISTANBUL".toLocaleLowerCase("tr") // "ıstanbul"

So this package is not here to fix toLocaleLowerCase. It exists for the cases around it:

  • Runtimes without Turkish ICU data. toLocaleLowerCase("tr") silently falls back to root-locale behaviour on a small-icu Node build, in some React Native setups and on older embedded runtimes. These functions carry their own mapping table, so the result never depends on how the host was compiled. Check what you have with Intl.Collator.supportedLocalesOf(["tr"]).
  • Everything toLocaleLowerCase does not do: diacritic folding for search, ASCII transliteration, URL slugs and Turkish alphabet collation — the operations below.
  • Explicitness. foldTr(a) === foldTr(b) is a deliberate comparison key, not a locale-tag argument that a refactor can drop.

If you already rely on ICU being present and you only need lowercasing, the built-in is the right call and you do not need a dependency for it.

Install

npm install trtext

Usage

import {
	toLowerCaseTr,
	toUpperCaseTr,
	foldTr,
	slugTr,
	sortTr,
	capitalizeTr,
} from "trtext"

toLowerCaseTr("İZMİR") // "izmir"
toLowerCaseTr("ISTANBUL") // "ıstanbul"
toUpperCaseTr("ığdır") // "IĞDIR"
capitalizeTr("istanbul") // "İstanbul"

foldTr("  ÇAĞRI  Merkezi ") // "cagri merkezi"
slugTr("Şanlıurfa'da Güneş") // "sanliurfada-gunes"

sortTr(["Üsküdar", "Zonguldak", "Çorum", "Iğdır"])
// ["Çorum", "Iğdır", "Üsküdar", "Zonguldak"]

Case-insensitive search that actually works

The common bug is a user typing istanbul and not matching a stored İSTANBUL. Fold both sides to one comparison key:

const matches = cities.filter((city) => foldTr(city).includes(foldTr(query)))

API

| Function | Description | | --- | --- | | toLowerCaseTr(s) | Lowercase with Turkish rules. I → ı, İ → i, and I + combining dot above → i. | | toUpperCaseTr(s) | Uppercase with Turkish rules. i → İ, ı → I. | | capitalizeTr(s) | First letter up, the rest down. | | titleCaseTr(s) | Capitalize every word, preserving the original spacing. | | asciifyTr(s) | Transliterate çğıöşüâîû to ASCII, preserving case. | | foldTr(s) | Turkish lowercase + diacritics stripped + whitespace collapsed. A comparison key for search and deduplication. | | slugTr(s, opts?) | URL slug. Options: separator (default "-"), preserveTurkish (default false). | | compareTr(a, b) | Comparator for Array.prototype.sort, using Turkish alphabet order. | | sortTr(strings) | New sorted array; the input is not mutated. | | TURKISH_ALPHABET | The 29 letters in collation order. |

Collation follows the Turkish alphabet, where ç follows c, ğ follows g, ı precedes i, ö follows o, ş follows s and ü follows u. The test suite asserts that sortTr produces exactly the same order as Intl.Collator("tr") on runtimes that ship Turkish collation data, and skips rather than fails on runtimes that do not.

Characters outside the Turkish alphabet (digits, punctuation, foreign letters) sort after it in code point order, so the ordering is always deterministic.

Related work

  • Intl.Collator and toLocaleLowerCase("tr") — the built-ins. Correct where ICU Turkish data is available; see the section above.
  • slugify — a general-purpose slugger with a much wider character map, but it lowercases with the default locale, so dotted and dotless i get mangled.
  • turkish-deasciifier — solves the opposite problem: guessing the missing diacritics in text typed on an ASCII keyboard.

Development

npm install
npm test # builds, then runs the suite on the compiled output

License

MIT


Neden gerekli

JavaScript'in toLowerCase() fonksiyonu bilinçli olarak yerel ayardan bağımsızdır, bu yüzden Türkçede hatalı çalışır: "I".toLowerCase() sonucu "ı" yerine "i" verir, "İ".toLowerCase() ise temiz bir "i" yerine üzerinde birleşen nokta taşıyan iki karakterlik bir dize döndürür.

toLocaleLowerCase("tr") ne olacak?

O doğru çalışıyor — Türkçe ICU verisi bulunan bir ortamda "İ" için tek karakterlik temiz bir "i" döndürür. Bu paket onu düzeltmek için değil, çevresindeki boşluklar için var: ICU verisi olmayan ortamlarda (small-icu Node derlemeleri, bazı React Native kurulumları) sonucun ortama göre değişmemesi için ve toLocaleLowerCase'in hiç yapmadığı işler için: arama için diyakritik katlama, ASCII çevirisi, URL slug'ı ve Türk alfabesi sıralaması.

Elinizde ICU varsa ve yalnızca küçük harfe çevirmek istiyorsanız, doğrusu dildeki hazır fonksiyonu kullanmaktır; buna bağımlılık eklemeniz gerekmez.

En sık görülen sorun

Kullanıcı istanbul yazıyor, veritabanındaki İSTANBUL kaydı bulunamıyor. foldTr her iki tarafı tek bir karşılaştırma anahtarına indirger ve sorun ortadan kalkar.

Kurulum ve kullanım

npm install trtext
import { toLowerCaseTr, slugTr, sortTr } from "trtext"

toLowerCaseTr("İZMİR") // "izmir"
slugTr("Şanlıurfa'da Güneş") // "sanliurfada-gunes"
sortTr(["Üsküdar", "Çorum"]) // ["Çorum", "Üsküdar"]

Sıralama Türk alfabesi düzenini izler: ç harfi c'den, ğ harfi g'den, ö harfi o'dan, ş harfi s'den ve ü harfi u'dan sonra gelir; ı harfi i'den önce gelir. Testler, Türkçe sıralama verisi bulunan ortamlarda sonucun Intl.Collator("tr") ile birebir aynı olduğunu doğrular.

Tüm fonksiyonların listesi için yukarıdaki API tablosuna bakın. Katkılar ve hata bildirimleri memnuniyetle karşılanır.