Türk İ Problemi: Noktalı Bir Harf Dünyanın Yazılımlarını Nasıl Bozuyor?
Türkçedeki i-İ ve ı-I ayrımı, dünya çapında yazılım hatalarının en ünlü kaynaklarından biri. Uygulamanız bir Türk kullanıcının bilgisayarında neden çöker, "title" neden "TİTLE" olur ve nasıl korunursunuz?

İçindekiler 7
Yazılım dünyasında "Turkish I problem" diye bilinen, Microsoft'tan Oracle'a kadar büyük şirketlerin dokümantasyonlarında ayrıca uyarı olarak geçen ünlü bir hata sınıfı var. Kaynağı bizim alfabemizin ta kendisi: Türkçede dört ayrı i harfi var. Çoğu dilde ise sadece iki.
Bir uygulama, ABD'deki geliştiricinin bilgisayarında kusursuz çalışıyor. Aynı uygulama, işletim sistemi dili Türkçe olan bir bilgisayarda açılınca giriş yapamıyor, ayar dosyasını okuyamıyor ya da tamamen çöküyor. Nedeni tek bir harf.
Kısaca:
- İngilizcede i büyüyünce I olur. Türkçede i büyüyünce İ, ı büyüyünce I olur.
- Büyük/küçük harf dönüşümü çoğu dilde sistemin diline göre yapılır; Türkçe bir sistemde "title" büyütülünce "TİTLE" olur ve "TITLE" ile eşleşmez.
- Python'da
"İ".lower()tek harf değil, iki karakterlik bir metin döndürür.- Çözüm: makineye yönelik metinlerde (anahtar kelimeler, dosya adları, protokoller) dil bağımsız dönüşüm; insana yönelik metinlerde açıkça Türkçe dönüşüm.
Dört i: Sorunun kaynağı
Latin alfabesini kullanan dillerin çoğunda bir harf çifti var: küçük i ve büyük I. Türkçe ise 1928'de Latin alfabesine geçerken iki ayrı ses için iki ayrı çift tanımladı:
| Küçük | Büyük | Unicode |
|---|---|---|
| i (noktalı) | İ (noktalı) | U+0069 → U+0130 |
| ı (noktasız) | I (noktasız) | U+0131 → U+0049 |
Unicode bu durumu şöyle çözdü: İngilizcedeki i ve I'yı olduğu gibi bıraktı, Türkçeye özgü İ ve ı için iki yeni karakter ekledi. Yani Türkçe bir metinde "i" ile İngilizce bir metindeki "i" aynı karakter. Farklı olan, onun büyük hâli.
İşte bu yüzden büyük/küçük harf dönüşümü, "hangi dile göre?" sorusunun cevabına bağlı hâle geliyor:
- İngilizce kurallarla:
i → I,I → i - Türkçe kurallarla:
i → İ,I → ı
Hata nasıl ortaya çıkıyor?
Birçok programlama dilinde büyük/küçük harf dönüşümü varsayılan olarak işletim sisteminin diline göre yapılıyor. Geliştirici bunun farkında olmadan şöyle bir kod yazıyor:
String komut = kullaniciGirdisi.toUpperCase();
if (komut.equals("QUIT")) {
cikisYap();
}
İngilizce bir bilgisayarda "quit" yazan kullanıcı çıkış yapabilir. Türkçe bir bilgisayarda ise "quit".toUpperCase() sonucu "QUİT" olur. "QUIT" ile eşleşmez, program çıkmaz. Java'nın kendi resmi dokümantasyonu bu durumu açıkça örnekliyor: Türkçe yerel ayarda "TITLE".toLowerCase() çağrısı "title" değil, noktasız ı ile "tıtle" döndürüyor.
Bu hata; HTTP başlıklarını, dosya uzantılarını (.HTML mi .html mi?), SQL anahtar kelimelerini, ayar dosyalarındaki anahtarları ve e-posta adreslerini karşılaştıran her yerde ortaya çıkabilir. "ID" alanını küçültüp "id" ile karşılaştıran bir kod, Türkçe sistemde "ıd" elde edip eşleşmeyi kaçırır.
Dillere göre durum
Java ve Kotlin
Java'da toUpperCase() ve toLowerCase() parametre verilmezse varsayılan yerel ayarı (default locale) kullanır. Makineye yönelik her dönüşümde Locale.ROOT verin:
"quit".toUpperCase(Locale.ROOT); // "QUIT" (her sistemde)
"istanbul".toUpperCase(Locale.forLanguageTag("tr")); // "İSTANBUL"
Kotlin 1.5 ile gelen uppercase() ve lowercase() fonksiyonları ise varsayılan olarak dil bağımsız çalışır; Türkçe dönüşüm için yerel ayarı açıkça vermeniz gerekir.
C# / .NET
.NET'te ToUpper() ve ToLower() geçerli kültürü kullanır. Microsoft'un dokümantasyonu bu sorunu adıyla anar. Çözüm ToUpperInvariant() ve karşılaştırmalarda StringComparison.OrdinalIgnoreCase kullanmaktır:
string.Equals(komut, "QUIT", StringComparison.OrdinalIgnoreCase);
JavaScript
JavaScript'te toUpperCase() ve toLowerCase() dil bağımsızdır; yani makine metinleri için güvenli. Ama bu sefer ters bir sorun var: Türkçe metinleri doğru büyütmek için toLocaleUpperCase('tr-TR') kullanmak gerekiyor:
"istanbul".toUpperCase(); // "ISTANBUL" (Türkçe için yanlış)
"istanbul".toLocaleUpperCase("tr-TR"); // "İSTANBUL"
Sitenizde başlıkları CSS ile büyütüyorsanız (text-transform: uppercase), HTML'de lang="tr" belirtmeyi unutmayın. Tarayıcılar dönüşümü bu etikete göre yapar; aksi halde "İstanbul" başlığınız "ISTANBUL" olarak görünür.
Python
Python'da str.upper() ve str.lower() dil bağımsızdır ve yerel ayardan etkilenmez. Ama Python'un sürprizi başka:
>>> "İ".lower()
'i̇'
>>> len("İ".lower())
2
Unicode'un genel kurallarına göre büyük noktalı İ küçültüldüğünde, noktayı korumak için "i" harfine bir birleşik nokta (U+0307) eklenir. Sonuç ekranda "i" gibi görünse de iki karakterdir. "İstanbul".lower() == "istanbul" karşılaştırması bu yüzden False döner. Aynı davranış Java'da Locale.ROOT ile de görülür.
Veritabanları ve arama
Sorun uygulama kodunda bitmez. Veritabanlarında büyük/küçük harf duyarsız arama da seçilen karşılaştırma kuralına (collation) bağlıdır. Türkçe olmayan bir kuralla çalışan bir arama kutusunda "ışık" araması "IŞIK"ı bulamayabilir; ya da tam tersine İngilizce kurallarla "i" ile "ı" farklı harfler sayıldığı için beklenmeyen sonuçlar çıkar.
Kullanıcıların Türkçe arama yaptığı bir sistemde, arama alanı için Türkçe karşılaştırma kuralı seçmek ya da aramayı normalize edilmiş bir sütun üzerinden yapmak gerekir.
Altın kural: Metnin kime ait olduğunu sorun
Bu karmaşayı tek bir soruyla çözebilirsiniz: Bu metin bir insana mı, bir makineye mi ait?
Makineye ait metinler (komutlar, anahtar kelimeler, dosya uzantıları, HTTP başlıkları, JSON alan adları, e-posta alan adları):
- Dil bağımsız dönüşüm kullanın: Java'da
Locale.ROOT, .NET'teInvariantveOrdinal. - Mümkünse hiç dönüştürmeyin, doğrudan büyük/küçük harf duyarsız karşılaştırın.
İnsana ait metinler (isimler, şehirler, başlıklar, ürün adları):
- Dönüşümü açıkça Türkçe kurallarla yapın.
- Kullanıcının dilini sistemin diline bırakmayın, bilinçli olarak belirtin.
Test için de basit bir öneri: uygulamanızın test ortamında varsayılan dili bir kez Türkçeye ayarlayıp tüm testleri çalıştırın. Java'da bu, JVM'i -Duser.language=tr -Duser.country=TR parametreleriyle başlatmak kadar kolay. Türk İ hatalarının çoğu ilk çalıştırmada kendini gösterir.
Sıkça sorulan sorular
Bu sorun sadece Türkçede mi var?
Türkçe ve aynı alfabe kuralını paylaşan Azerice en bilinen örnekler. Ama dile bağlı büyük/küçük harf kuralları başka dillerde de var; örneğin Litvanca ve Almancadaki ß harfinin büyük hâli gibi. Türkçe, en yaygın ve en çok hata üreten örnek olduğu için sorun onun adıyla anılıyor.
Neden Unicode tek bir "i" tanımlamadı?
Unicode, daha önceki karakter setleriyle uyumlu olmak zorundaydı. İngilizce i ve I, en eski ASCII karakter setinde zaten vardı. Türkçe İ ve ı'yı ayrı karakter olarak eklemek, mevcut milyarlarca metni bozmamanın tek yoluydu.
Uygulamam Türkiye'de kullanılmıyorsa etkilenir miyim?
Evet. Dünyanın herhangi bir yerinde, işletim sistemi dili Türkçe olan tek bir kullanıcı ya da sunucu yeterli. Bu yüzden uluslararası yazılım projelerinde Türkçe yerel ayarla test yapmak iyi bir alışkanlık olarak kabul edilir.
Web sitemde bu sorunu nasıl önlerim?
HTML'de lang="tr" belirtin, büyük harf gösterimlerini CSS text-transform ile yapın ve JavaScript'te Türkçe metinler için toLocaleUpperCase('tr-TR') kullanın. URL ve slug üretiminde ise Türkçe karakterleri bilinçli bir tabloyla dönüştürün (ı → i, İ → i gibi).
Tek bir noktanın bu kadar hataya yol açması, yazılımda küçük ayrıntıların ne kadar önemli olduğunu gösteriyor. Türkçe kullanıcılar için sorunsuz çalışan web ve mobil uygulamalar geliştirmek isterseniz web uygulama geliştirme sayfamızdan bize ulaşabilirsiniz. Tarihin daha pahalı yazılım hataları için bu yazımıza da göz atabilirsiniz.
Kaynaklar
learn.microsoft.comBest Practices for Comparing Strings in .NET - .NETLearn how to compare strings effectively in .NET applications.unicode.orgUnicode: SpecialCasing.txt
MDN Web DocsString.prototype.toLocaleUpperCase() - JavaScript | MDNThe toLocaleUpperCase() method of String values returns this string converted to upper case, according to any locale-specific case mappings.
Python documentationBuilt-in TypesThe following sections describe the standard types that are built into the interpreter. The principal built-in types are numerics, sequences, mappings, classes, instances and exceptions. Some colle...

