Yazılım & ERP 7 dk okuma
JavaScript'te Türkçe Karakter Sorunu: toLowerCase Tuzağı ve Bozulan Slug'lar
toLowerCase ve toUpperCase Türkçe'de yanlış sonuç verir. Noktalı ve noktasız i sorunu, aksan temizlemenin neden ı harfini atladığı, slug üretimi, sıralama ve arama.
Yazan Şafak Yılmaz · Kurucu, Yazılım Geliştirici
Kısa cevap
JavaScript'in toLowerCase ve toUpperCase metotları varsayılan olarak Türkçe kurallarını uygulamaz: 'istanbul'.toUpperCase() sonucu İSTANBUL değil ISTANBUL olur, 'IŞIK'.toLowerCase() ise ışık değil işik döndürür. Doğrusu toLocaleUpperCase('tr') ve toLocaleLowerCase('tr') kullanmaktır. Slug üretiminde yaygın olan NFD ile aksan temizleme yöntemi ise ı harfini hiç dönüştürmez, çünkü ı ayrı bir harftir ve ayrışmaz. Türkçe karakterler için açık bir eşleme tablosu kullanılmalıdır.
Müşteri adı arandı, kayıt bulunamadı#
Bir bayi yönetim paneli. Arama kutusuna “ışık” yazılıyor, sonuç yok. “IŞIK” yazılıyor, yine yok. Kayıt veritabanında duruyor, isim doğru yazılmış.
Sorun aramanın kendisinde değildi. Sorgu doğru çalışıyordu, karşılaştırılan metin yanlıştı.
Uygulama, aramayı küçük harfe çevirip karşılaştırıyordu. Kullanıcının yazdığı “IŞIK” küçültüldüğünde “işik” oluyordu. Veritabanındaki kayıt ise “ışık” olarak duruyordu. İki metin birbirine benziyor ama aynı değil, çünkü biri noktalı i diğeri noktasız ı içeriyor.
Bu hata Türkçe yazılım geliştiren hemen her ekibin başına geliyor ve genellikle üretimde, gerçek veriyle karşılaşıldığında ortaya çıkıyor.
Dört harf, iki yanlış eşleme#
İngilizce’de i harfinin iki hali vardır: i ve I. Türkçe’de dört hali vardır: i, İ, ı, I.
Unicode’un varsayılan kuralında büyük I’nın küçüğü noktalı i’dir. Türkçe’de ise büyük I’nın küçüğü noktasız ı, büyük İ’nin küçüğü noktalı i’dir. Varsayılan eşleme bu iki harfi yanlış karşılar ve dil bilgisi olmadan yapılan her dönüşüm sessizce bozulur.
Aşağıdaki sonuçlar Node.js üzerinde çalıştırılarak alınmıştır.
| İşlem | Sonuç | Doğru mu |
|---|---|---|
"istanbul".toUpperCase() |
ISTANBUL |
Hayır |
"istanbul".toLocaleUpperCase("tr") |
İSTANBUL |
Evet |
"IŞIK".toLowerCase() |
işik |
Hayır |
"IŞIK".toLocaleLowerCase("tr") |
ışık |
Evet |
"INFINITECAT".toLocaleLowerCase("tr") |
ınfınıtecat |
Türkçe için evet, alan adı için felaket |
Son satır özellikle önemli. Türkçe kuralını her yere uygulamak da yanlıştır; çözüm, dönüşümü düşünmeden her yerde Türkçe’ye sabitlemek değil.
Alan adı, e-posta adresi, dosya uzantısı, HTTP başlığı, API anahtarı ve kod içindeki anahtar kelimeler dil bağımsızdır. Bunları Türkçe kuralıyla küçültürseniz I harfleri noktasız ı’ya döner ve karşılaştırma tutmaz. Kural şu: kullanıcıya gösterilecek metinde Türkçe yerel ayarını kullanın, makineye gidecek değerde kullanmayın.
Aksan temizleme neden ı harfini atlıyor#
Slug üretiminde en çok kopyalanan yöntem şudur: metni NFD ile ayrıştır, birleşen işaretleri sil, kalanı al. Tek satır, zarif görünüyor.
Türkçe’de eksik çalışıyor.
Bu yöntem bir harfin temel harf ile ayrı bir işaretin birleşimi olduğu durumlarda işe yarar. Türkçe karakterlerin çoğu böyledir, ama hepsi değil.
| Harf | NFD + işaret silme sonucu | Neden |
|---|---|---|
| ç | c |
Ayrışıyor |
| ğ | g |
Ayrışıyor |
| ö | o |
Ayrışıyor |
| ş | s |
Ayrışıyor |
| ü | u |
Ayrışıyor |
| ı | ı |
Ayrışmıyor, ayrı bir harf |
| İ | I |
Ayrışıyor ama büyük I çıkıyor |
Noktasız ı, temel harf artı işaret değildir. Kendi başına bir harftir ve ayrıştırma işleminden etkilenmez.
Sonucu somut görmek için: "Işıklı Çağrı Şubesi" metni önce küçültülüp sonra bu yöntemle temizlendiğinde ortaya isıklı cagrı subesi çıkıyor. İçinde hâlâ noktasız ı var. Üstelik baştaki I harfi varsayılan küçültmeyle noktalı i’ye dönüştüğü için kelime de yanlış yazılmış durumda.
Çözüm açık bir eşleme tablosudur. Türkçe’ye özgü altı harf için karşılıkları elle tanımlayın, sonra genel temizliği uygulayın. Sıra önemli; eşlemeyi önce yapmazsanız aynı tuzağa düşersiniz.
Hazır bir paket kullanmayı düşünüyorsanız seçmeden önce tek bir test yapın: içinde noktasız ı ve büyük İ geçen bir metni verin ve çıktıya bakın. Türkçe desteği olduğunu söyleyen paketlerin önemli bir bölümü bu iki harfi doğru işlemez, çünkü arkada yine aynı aksan temizleme yöntemini kullanırlar.
Aynı hata başka yerlerde nasıl görünür#
Büyük küçük harf dönüşümü masum bir işlem gibi durduğu için kod incelemelerinde kimsenin dikkatini çekmez; oysa bir uygulamada kullanıcı metninin küçültüldüğü yerlerin sayısı genellikle geliştiricinin tahmininden çok daha fazladır ve bunların her biri ayrı bir hata noktasıdır.
En sık karşılaşılan dört yer şöyle sıralanabilir.
Giriş ve kullanıcı adı karşılaştırması. Kullanıcı adını küçültüp veritabanındaki kayıtla karşılaştıran bir sistem, içinde I ya da İ geçen adlarda kullanıcıyı kendi hesabından kilitleyebilir. Kayıt sırasında bir kural, giriş sırasında başka bir kural uygulanmışsa sorun yalnızca o kullanıcılarda görünür ve destek ekibi sebebini bulamaz.
Dosya adları. Yüklenen belgelerin adı Türkçe karakter içeriyorsa ve sunucu tarafında bu ad temizleniyorsa, aynı dosya iki farklı sistemde iki farklı adla saklanabilir. Sonradan eşleştirme yapmak gerektiğinde kayıtlar tutmaz.
Dışa aktarılan raporlar. Muhasebe ya da pazaryeri sistemlerine gönderilen dosyalarda alan değerleri büyük harfe çevriliyorsa, varsayılan dönüşüm İ yerine I üretir ve karşı taraftaki doğrulama bunu farklı bir değer olarak okur.
Toplu mesaj gönderimi. Kısa mesajlarda Türkçe karakter kullanımı mesajın karakter sınırını değiştirir; metni dönüştürürken yapılan bir hata tek mesaj olarak planlanan gönderimi iki mesaja bölerek maliyeti ikiye katlayabilir.
Bu dört örneğin ortak yanı şu: hiçbiri çökmez. Hepsi çalışır ve yanlış sonuç üretir.
Sıralama da varsayılanla çalışmıyor#
Aynı sorunun daha az fark edilen bir kardeşi sıralamadır. Varsayılan dizi sıralaması alfabeye değil karakter kodlarına bakar.
Dört kelimeyi varsayılan yöntemle sıraladığınızda cam, iyi, çay, ılık sırası çıkıyor. Türkçe yerel ayarıyla karşılaştırdığınızda ise doğru sonuç geliyor: cam, çay, ılık, iyi.
Bu fark ürün listelerinde, bayi ve şube dizinlerinde, il ilçe seçim kutularında doğrudan görünür. Kullanıcı listeyi alfabetik sanır, Ç ile başlayan markayı C’lerin arasında arar, bulamaz ve ürün yok sanır.
Düzeltmesi tek satır. Karşılaştırma fonksiyonuna tr yerel ayarını vermek yeterli.
Bu düzeltmenin yalnızca uygulama katmanında yapılması çoğu zaman yetmez; veritabanından sıralı gelen bir liste, uygulamada yeniden sıralanmadığı sürece veritabanının collation ayarına göre dizilir ve iki katman farklı kural uyguluyorsa aynı liste sayfa yenilendiğinde farklı sırada görünebilir.
URL tarafında ne yapmalı#
Türkçe karakterli alan adı almak mümkün. Noktalı adresler Punycode ile kodlanır ve teknik olarak çalışır.
Pratikte iki sorun çıkıyor. Birincisi paylaşım: adres kopyalandığında bazı uygulamalarda kodlanmış uzun hali görünür ve okunmaz hale gelir. İkincisi güven: kullanıcı beklediğinden farklı bir adres gördüğünde tereddüt eder.
Sayfa adreslerinde ise durum daha net. Türkçe karakterli bir slug teknik olarak geçerlidir, arama motorları işleyebilir. Buna rağmen ASCII karşılık kullanmak yaygın tercih, çünkü analitik raporlarında aynı sayfa farklı kodlanmış biçimlerde ayrı satırlar olarak görünebiliyor ve bu da arama performansını ölçmeyi zorlaştırıyor.
Burada asıl kritik nokta tutarlılıktır. Slug üretim kuralınızı bir kez belirleyin ve değiştirmeyin; sonradan değişen kural, eski adreslerin kırılması ve yönlendirme borcu demektir.
Site içi aramada ek bir katman var#
Türkçe sondan eklemeli bir dildir. Kullanıcı “fatura” arar, içerikte “faturanın”, “faturalandırma”, “faturalara” geçer. Harf harf eşleşme arayan bir arama bu kayıtları bulamaz.
Bu, karakter sorununun üstüne binen ayrı bir problemdir ve ikisi karıştırılmamalıdır. Birincisi büyük küçük harf dönüşümüyle, ikincisi kelime kökü bulmayla ilgilidir.
Küçük siteler için pratik çözüm, arama dizinini oluştururken hem metni Türkçe kurallarıyla küçültmek hem de yaygın ekleri kırpmaktır. Daha büyük kurulumlarda arama motorunun Türkçe analizörünü açmak doğru yoldur; çoğu arama altyapısında bu hazır gelir ama varsayılan olarak kapalıdır ve kimse açmayı akıl etmediği için yıllarca eksik sonuç döndürülür.
Kurumsal yazılım projelerinde bu ayarın atlanması, kullanıcıların sisteme güvenini en hızlı kaybettiren şeylerden biri.
Hangi dillerde aynı sorun var#
Bu davranış JavaScript’e özgü değil. Aynı ayrım Unicode’un kendisinden geldiği için, dil ne olursa olsun varsayılan dönüşüm Türkçe’yi bilmez ve yerel ayar açıkça verilmediği sürece aynı yanlış sonucu üretir.
Python’da .upper() ve .lower() metotları da dilden bağımsız çalışır, dolayısıyla Türkçe metinlerde aynı hatayı yapar. Java’da toLowerCase() çağrısı parametresiz kullanıldığında sistemin varsayılan yerel ayarını alır; bu, geliştiricinin makinesinde doğru çalışıp sunucuda yanlış çalışan ve bu yüzden teşhisi en zor olan hata tiplerinden birini üretir. C# tarafında da benzer biçimde kültür bilgisi veren ve vermeyen iki ayrı aşırı yükleme bulunur.
Kural her ortamda aynı. Dönüşümün hangi dile göre yapılacağını siz söyleyin, varsayılana bırakmayın.
Kontrol listesi#
Mevcut bir projede bu sorunları aramak isterseniz sırayla şunlara bakın.
- Kod içinde
toLowerCasevetoUpperCaseçağrılarını tarayın. Kullanıcı metni üzerinde çalışan her birini yerel ayarlı sürümle değiştirin. - Alan adı, e-posta ve anahtar karşılaştırmalarında yerel ayar kullanmadığınızdan emin olun.
- Slug üretim fonksiyonunu
Işıklı Çağrı Şubesimetniyle test edin. Çıktıda ı harfi kalıyorsa eşleme tablonuz eksik. - Alfabetik listeleri Ç, Ğ, İ, Ö, Ş, Ü ile başlayan kayıtlar ekleyip kontrol edin.
- Site içi aramada ekli kelimelerle test yapın.
Beş maddenin tamamı yarım günde taranır. Bulunan hataların düzeltilmesi genelde daha da kısa sürer, çünkü sorun mimaride değil tek tek satırlardadır. Bu taramayı yeni bir projeye başlarken değil, mevcut projede bir kez yapıp sonucu takıma not olarak bırakmak en verimli yoldur.
Bu hatayı biz de yaptık#
Bu yazının çıkış noktası teorik bir merak değil. Kendi içerik araçlarımızda bir metni büyük harfe çevirirken varsayılan metodu kullandık ve “iyi” kelimesi “Iyi” olarak çıktı. Başlıkta görünce fark ettik.
Hatanın can sıkıcı tarafı, testten geçmesiydi. Kod çalışıyordu, istisna fırlatmıyordu, çıktı üretiyordu. Yalnızca yanlış üretiyordu.
Türkçe için yazılan yazılımlarda bu kategorideki hatalar en pahalı olanlardır, çünkü sessizdirler. Bir hata mesajı sizi uyarmaz; ancak bir kullanıcı “bu isim listede yok” dediğinde ortaya çıkarlar.
Sitenizin teknik tarafını ya da mevcut bir yazılımın Türkçe davranışını konuşmak isterseniz bize yazın. Web sitesi kurulumu, sayfa hızı, yapay zekâ aramalarında görünürlük ve ERP tarafı için ayrı yazılarımız var; genel sorular için SSS sayfasına ya da SEO uyumlu web sitesi sayfasına bakabilirsiniz.
Kaynaklar#
SSS
Bu konuda sık sorulanlar#
toLowerCase neden Türkçe'de yanlış çalışıyor?
Çünkü varsayılan davranış dile değil Unicode'un genel kuralına bağlıdır. Genel kuralda büyük I harfinin küçüğü noktalı i'dir. Türkçe'de ise büyük I'nın küçüğü noktasız ı, büyük İ'nin küçüğü noktalı i'dir. Dört ayrı harf vardır ve varsayılan eşleme bunların ikisini yanlış karşılar. Doğru sonuç için toLocaleLowerCase('tr') ve toLocaleUpperCase('tr') kullanılır.
NFD ile aksan temizleme neden yetmiyor?
Yaygın slug yöntemi metni NFD ile ayrıştırıp birleşen işaretleri silmektir. Bu yöntem ç, ğ, ö, ş ve ü için çalışır çünkü bunlar temel harf ile bir işaretin birleşimidir. Noktasız ı ise ayrı bir koddur ve ayrışmaz; işlemden hiç etkilenmeden geçer. Sonuçta URL'de ı harfi kalır. Türkçe karakterler için açık bir eşleme tablosu şarttır.
URL'de Türkçe karakter kullanmak SEO'ya zarar verir mi?
Doğrudan bir ceza yoktur, tarayıcılar ve arama motorları yüzde kodlamasıyla kodlanmış adresleri işleyebilir. Pratik sorun paylaşımda çıkar: kopyalanan adres uzun ve okunaksız hale gelir, bazı eski sistemler bağlantıyı kırar, analitik raporlarında aynı sayfa farklı biçimlerde görünebilir. Bu nedenle slug'larda ASCII karşılık kullanmak yaygın tercihtir.
Sıralama neden bozuluyor?
Varsayılan dizi sıralaması karakterlerin kod değerine göre yapılır, alfabeye göre değil. Bu yüzden ç ve ı gibi harfler listenin sonuna düşer. Türkçe alfabe sırası için localeCompare metodunu tr yerel ayarıyla kullanmak gerekir; böylece cam, çay, ılık, iyi sıralaması doğru çıkar.
Veritabanı tarafında ne yapmalı?
Karşılaştırma ve sıralama davranışı collation ayarına bağlıdır. Uygulama katmanında Türkçe'ye göre küçülttüğünüz bir metni, farklı collation kullanan bir sütunla karşılaştırdığınızda eşleşme kaçabilir. Kural basit: dönüştürmeyi tek bir katmanda yapın ve her yerde aynı kuralı uygulayın.
İlgili hizmetler
SEO Uyumlu Web Sitesi
Google'da üst sıralara çıkan, saniyenin altında açılan ve dönüşüm üreten kurumsal web siteleri. Teknik SEO, Core Web Vitals ve yapılandırılmış veri baştan kurulur.
İnceleKurumsal Yazılım · ERP · CRM
Excel ve WhatsApp'la yürüyen süreçleri tek platformda toplayan, işletmenize özel ERP, CRM ve otomasyon yazılımları. Web tabanlı, mobil uyumlu, mevcut sistemlerinize entegre.
İnceleDevamı
İlgili yazılar#
Yazılım & ERP 7 dk okuma
Trendyol API Entegrasyonu: 426 Hatası ve Kapanan Sipariş Servisi
Trendyol entegrasyonunuz günde üç kez 426 veriyorsa sistem bozulmadı. Eski sipariş servisi kapanıyor: v2 geçişi ve servis limitleri.
OkuYazılım & ERP 7 dk okuma
e-Fatura ve e-Arşiv Entegrasyonu: Kimler Zorunlu, Nasıl Bağlanır?
e-Fatura ve e-Arşiv kimler için zorunlu, aradaki fark ne? GİB portalı, özel entegratör ve doğrudan entegrasyon karşılaştırması, teknik adımlar ve sık hatalar.
OkuYazılım & ERP 7 dk okuma
Trendyol ve Hepsiburada Entegrasyonu: Stok ve Sipariş Senkronizasyonu
Trendyol ve Hepsiburada entegrasyonunda stok ve sipariş senkronizasyonu nasıl kurulur? Aşırı satış nedenleri, doğru mimari, 2026 maliyetleri ve devreye alma adımları.
Oku→ Başlayalım
Bu konuda yardım ister misiniz?#
Yazıda anlatılanları projenize uygulamak için ücretsiz keşif görüşmesi yapalım.