Türkçe yerelleştirme: arayüzü Türkçeye uyarlamak
Türkçe yerelleştirme, bir ürünün metnini, biçimlerini ve kodunu Türkçe konuşan kullanıcıya göre uyarlamaktır. Arayüzde dikkat isteyen yerler uzayan metin, İ ve ı harfleri, değişkenlere gelen ekler, tarih ve para biçimi, alfabetik sıralama ve yazı tipidir. Bunların çoğunu doğru bir lang özniteliği ve tarayıcının Intl araçları çözer.
Kısaca
Bir ürünü Türkçeye çevirmek işin metin kısmıdır. Yerelleştirme, metnin ekranda nasıl durduğunu da kapsar: kutuya sığıyor mu, büyük harfe doğru dönüyor mu?
- Türkçe etiketler çoğu zaman İngilizcesinden uzundur. Sabit genişlikli butonlar ilk kırılan yerdir.
- Türkçede iki ayrı i vardır.
toUpperCase()"istanbul" kelimesini "ISTANBUL" yapar, Türkçe kuralla doğrusu "İSTANBUL". - Ad, şehir ya da ürün adı gibi değişkenlere gelen ek, kelimenin sesine göre değişir. Sabit bir
{ad}'aşablonu birçok adda yanlış ek üretir. - Tarih, sayı, para birimi ve sıralama için kendi kodunuzu yazmayın.
Intlbu işleritr-TRkurallarıyla yapar. - Yazı tipinizin ğ, ş, ı ve İ harflerini içerdiğini kontrol edin.
Yerelleştirme ve i18n: fark ne?
W3C iki kavramı ayırır. Yerelleştirme (localization, kısaca l10n), bir ürünün belli bir pazarın dil, kültür ve diğer gereksinimlerine uyarlanmasıdır. Uluslararasılaştırma (internationalization, kısaca i18n) ise ürünü bu uyarlamayı kolaylaştıracak biçimde tasarlayıp geliştirmektir.
Kısaltmalardaki sayılar harf sayısıdır. İngilizce kelimede l ile n arasında 10, i ile n arasında 18 harf vardır.
W3C, yerelleştirmenin çoğu zaman yalnızca arayüz ve belge çevirisiyle eş tutulduğunu da yazar. Oysa listesinde sayı, tarih ve saat biçimleri, para birimi, simgeler ve sıralama da vardır. Bu rehber Türkçe için o listenin arayüz tarafına bakıyor.
Ben işi şöyle bölerim. i18n, geliştiricinin bir kez yaptığı hazırlıktır: metinleri koddan ayırmak, biçimleri Intl'e bırakmak. l10n ise her dil için tekrarlanan işin kendisidir.
Metin uzaması: arayüz Türkçede ne kadar büyür?
W3C'nin "Text size in translation" makalesi, IBM'in tasarım yönergelerinden bir tablo aktarır. Tabloya göre kısa metinler oransal olarak en çok uzar. 10 karaktere kadar bir İngilizce metin, Avrupa dillerinde ortalama %200–300 boyuta çıkabilir.
| İngilizce kaynaktaki karakter sayısı | Ortalama uzama |
|---|---|
| 10'a kadar | %200–300 |
| 11–20 | %180–200 |
| 21–30 | %160–180 |
| 31–50 | %140–160 |
| 51–70 | %151–170 |
| 70'ten fazla | %130 |
Tablo: W3C'nin aktardığı IBM oranları, İngilizceden Avrupa dillerine. 51–70 satırı kaynaktaki gibidir.
Tablo Türkçeye özel değil. Ben bu yüzden kendi ürününüzün metinleriyle ölçmenizi öneririm. Aşağıdaki çiftler benim örneklerim; bazı kelimeler kısalır, cümle kuran etiketler belirgin biçimde uzar.
| İngilizce | Türkçe | Karakter |
|---|---|---|
| Settings | Ayarlar | 8 → 7 |
| Save changes | Değişiklikleri kaydet | 12 → 21 |
| Personalized | Kişiselleştirilmiş | 12 → 18 |
| Forgot password? | Şifrenizi mi unuttunuz? | 16 → 23 |
| Unsaved changes | Kaydedilmemiş değişiklikler | 15 → 27 |
Türkçenin ayrı bir sorunu tek kelimelik uzunluktur. Türkçe ekleri kelimenin sonuna art arda bağlar, bu yüzden "Kişiselleştirilmiş" gibi kelimeler bölünmeden uzar. W3C de Almanca bileşik isimler için aynı uyarıyı yapar: bu kelimeler kendiliğinden satır atlamayabilir.
W3C'nin tasarıma önerisi esnek yerleşimdir. Metnin akmasına izin verin ve küçük sabit genişlikli kutulardan kaçının. Kısaltmaya başvurmadan önce iyi düşünün, çünkü başka diller aynı kısaltmayı kuramayabilir. Veritabanı alan genişliklerini de buna göre ayarlayın.
Benim pratik testim basit. Bir ekranı tasarlarken en uzun Türkçe etiketi koyarım, sonra 320 piksel genişlikte bakarım. Buton iki satıra iniyor ama okunuyorsa sorun yok. Metin kesiliyor ya da taşıyorsa düzeltmek gerekir.
Büyük harf, küçük harf ve İ/ı sorunu
Türkçede iki ayrı i harfi ve iki büyük-küçük harf eşleşmesi vardır: i ile İ, ı ile I. Unicode'un varsayılan kuralı ise i'yi I'ya çevirir. MDN, Türkçe gibi bazı dillerde bu yüzden toUpperCase() ile toLocaleUpperCase() sonucunun farklı olabileceğini yazar.
MDN'nin örneği de Türkçeden: "istanbul", toLocaleUpperCase("en-US") ile "ISTANBUL", toLocaleUpperCase("TR") ile "İSTANBUL" olur. UX writing rehberinde bu farka kısaca değinmiştim. Burada bu farkın kodda nerede sorun çıkardığına bakıyorum.
Geri dönüşte veri kaybı
MDN, büyük-küçük harf çevriminin her zaman karakter karakter bire bir olmadığını ve sonucun uzunluğunun değişebileceğini not eder. Türkçede bunu iki yönde görürsünüz.
- "İSTANBUL" metnini
toLowerCase()ile küçülttüğümde Node.js 24'te "i̇stanbul" çıktı. Baştaki harf, i ile ayrı bir birleşen noktadan oluşuyor. Metin bir karakter uzadı. - "ılık" kelimesi önce
toUpperCase()ile "ILIK" oluyor. Geri küçültünce "ilik" çıkıyor ve kelimenin anlamı değişiyor.
Bu iki örnek arama, filtre ve tekilleştirme kodunu bozar. "İzmir" yazan kullanıcı, küçük harfe çevrilmiş "izmir" kaydını bulamayabilir. Arama kutularında bu yüzden karşılaştırmayı toLocaleLowerCase("tr") ya da Intl.Collator ile yaparım. Arama ve otomatik tamamlama kalıbında da aynı normalizasyon gerekir.
Bir istisna var. E-posta adresi, kullanıcı adı ya da kod içi anahtar gibi teknik değerleri Türkçe kuralla küçültmeyin. Bunlar dilden bağımsız kalmalı. Ben görünen metin için "tr", kimlik ve anahtar için dilden bağımsız çevrimi kullanırım.
CSS text-transform ve lang
Başlıkları ya da butonları CSS ile büyük harfe çeviriyorsanız sonuç lang özniteliğine bağlıdır. MDN'ye göre text-transform dile özgü harf kurallarını dikkate alır ve dili HTML'deki lang özniteliğinden okur. Türkçe bu kuralların listesindedir.
İlk baktığım yer sayfanın kökü: <html lang="tr"> var mı? Sonra Türkçe sayfadaki İngilizce marka adlarının lang="en" ile işaretlenip işaretlenmediğine bakarım. Çeviri dosyasından gelen metin dili yanlış işaretlenmiş bir bileşende duruyorsa, CSS onu da yanlış büyütür.
MDN, dile özgü harf desteğinin tarayıcıdan tarayıcıya değiştiğini de not eder. Bu yüzden büyük harfli başlıkları gerçek cihazlarda kontrol edin. Aşağıdaki test, sizin tarayıcınızın ne yaptığını gösteriyor.
Türkçe testi: tarayıcınız ne yapıyor?
İlk alana bir kelime yazın; sonuçlar yazdıkça değişir. "Iğdır", "ılık" ya da "istanbul" gibi i ve ı içeren kelimeler farkı en iyi gösterir. Altta aynı sayı ve tarihin iki dildeki biçimini, en altta da bir listenin iki sıralamasını görürsünüz.
Aşağıdakiler varsayılan örneklerin çıktılarıdır. JavaScript açıkken alanları değiştirip sonucu canlı görebilirsiniz.
1. Büyük ve küçük harf
toUpperCase()- ISTANBUL ILIKTürkçe için yanlış
toLocaleUpperCase("tr")- İSTANBUL ILIK
- CSS uppercase,
lang="en" - istanbul ılık
- CSS uppercase,
lang="tr" - istanbul ılık
- Türkçe büyük harften geri,
toLowerCase() - i̇stanbul ilik14 karakter
- Aynısı,
toLocaleLowerCase("tr") - istanbul ılık13 karakter
2. Sayı, para ve tarih
Bu bir sayı olarak okunamadı. Örnek: 1234567,89
Para birimi
| Biçim | tr-TR | en-US |
|---|---|---|
| Sayı | 1.234.567,89 | 1,234,567.89 |
| Para birimi | ₺1.234.567,89 | TRY 1,234,567.89 |
| Kısa tarih | 3.11.2026 | 11/3/26 |
| Uzun tarih | 3 Kasım 2026 | November 3, 2026 |
| Tam tarih | 3 Kasım 2026 Salı | Tuesday, November 3, 2026 |
3. Alfabetik sıralama
Varsayılan sort()
- Ankara
- Iğdır
- Ordu
- Uşak
- Zonguldak
- Çorum
- Ödemiş
- Ünye
- İzmir
- Şanlıurfa
Intl.Collator("tr")
- Ankara
- Çorum
- Iğdır
- İzmir
- Ordu
- Ödemiş
- Şanlıurfa
- Uşak
- Ünye
- Zonguldak
10 öğeden 9 tanesi iki listede farklı sırada.
Türkçe kuralla “İSTANBUL ILIK”, kuralsız “ISTANBUL ILIK”. Para: ₺1.234.567,89 ve TRY 1,234,567.89. Sıralamada 10 öğeden 9 tanesi farklı yerde.
Bütün sonuçları sizin tarayıcınız hesaplıyor: JavaScript'in yerleşik toUpperCase, toLocaleUpperCase, Intl ve CSS text-transform. Başka bir tarayıcıda ya da eski bir sürümde farklı çıktı görebilirsiniz. Test de bunu görmeniz için var. Sayfa hiçbir veri göndermez.
Büyük harften geri dönüşteki karakter sayısına dikkat edin. toLowerCase() satırı bir karakter fazla gösteriyorsa, o fazla karakter İ harfinden kalan birleşen noktadır. Ekranda fark etmeyebilirsiniz ama veritabanındaki eşleşme bozulur.
Değişkenlere ek: ünlü uyumu ve ICU MessageFormat
"{ad}'a gönder" şablonu Burak için doğru, Ayşe için yanlıştır. Türkçede ek, kelimenin son ünlüsüne ve son sesine göre değişir. Kuralın kendisini ve bir ek hesaplayıcıyı UX writing rehberinde anlattım. Burada konu, kuralın çeviri dosyasına nasıl taşınacağı.
ICU select ne sağlar?
Birçok çeviri kütüphanesi ICU MessageFormat sözdizimini kullanır. ICU belgelerine göre select argümanı, alt mesajı sabit bir anahtar kümesinden seçer. Belgedeki örnek cinsiyet üzerinden kuruludur ve bir other seçeneği taşır.
ICU'nun iki önerisi Türkçe için de geçerli. Mesaj tek bir birim olarak yazılıp çevrilmeli; parçaları birleştirmek çevirmenin cümleyi yeniden kurmasını engeller. Karmaşık argümanlar da mümkünse mesajın en dışında durmalı, alt mesajlar tam cümle olmalı.
Benim önerim: eki kodda seçip select'e vermek
ICU Türkçe ünlü uyumunu kendisi hesaplamaz. Ben bu yüzden ek türünü kodda hesaplayıp mesaja bir anahtar olarak veririm. Mesaj dosyasında da her ek için tam cümle yazarım:
{ekTuru, select,
a {{ad}’a gönderildi.}
e {{ad}’e gönderildi.}
ya {{ad}’ya gönderildi.}
ye {{ad}’ye gönderildi.}
other {Alıcı: {ad}. Gönderildi.}
}
other kolu, kodun ek türünü bilemediği durumlar için eksiz bir cümledir. Kemal ya da Hilal gibi istisna adlarda kodunuz eki güvenle seçemiyorsa, bu kol yanlış bir ekten iyidir.
Kesme işaretine dikkat edin. ICU'da düz ASCII kesme işareti (') sözdiziminde tırnak işi görür. ICU 4.8'den beri yalnızca tırnaklanması gereken bir karakterin hemen önündeyse tırnak başlatır. ICU, okunacak metin için tipografik kesme işaretini (’, U+2019) önerir. Türkçede özel adlara gelen ekler kesme işaretiyle ayrılır, yani bu öneri doğrudan Türkçe metni ilgilendirir.
Tarih, sayı ve para birimi
Türkçede ondalık ayırıcı virgül, binlik ayırıcı noktadır. İngilizcede tersi geçerlidir. Bu farkı elle yazılmış bir biçimlendiriciyle tutturmak zordur; Intl.NumberFormat ve Intl.DateTimeFormat bunu dile göre yapar.
Aşağıdaki çıktıları 3 Kasım 2026'da Node.js 24.18.0 ile çalıştırdım:
| Kod | tr-TR | en-US |
|---|---|---|
| Sayı, 1234567.891 | 1.234.567,891 | 1,234,567.891 |
| Para, TRY | ₺1.234.567,89 | TRY 1,234,567.89 |
| Yüzde, 0.25 | %25 | 25% |
| Tarih, varsayılan | 03.11.2026 | 11/3/2026 |
Tarih, dateStyle: "long" | 3 Kasım 2026 | November 3, 2026 |
Tablodaki iki ayrıntıya kod incelemesinde özellikle bakarım. Türkçede yüzde işareti sayının önüne gelir. en-US ise lira için ₺ simgesi yerine "TRY" kodunu yazar. Kodda "%" + oran ya da tutar + " TL" görürsem Intl ile değiştirmeyi öneririm.
MDN'nin örneği tarihteki riski gösterir: aynı gün en-US ile "12/19/2012", en-GB ile "19/12/2012" olur. 3.11.2026 gibi bir tarih, ay-gün sırasına alışmış biri için 11 Mart'tır. Bu yüzden belirsiz tarihlerde ayı yazıyla gösteririm: "3 Kasım 2026".
Girdi tarafını da unutmayın. Türkiye'deki kullanıcı tutar alanına "1.250,50" yazar. Alan bunu 1,25 olarak okursa ödeme ekranında ciddi bir hata çıkar. Mobil form klavyesi kalıbında anlattığım inputmode="decimal" klavyeyi açar, ama virgülü doğru okumak yine sizin kodunuzun işidir.
Alfabetik sıralama: Intl.Collator
JavaScript'in varsayılan sort() metodu metni karakter kodlarına göre sıralar. Ç, Ğ, İ, Ö, Ş ve Ü bu kodlarda Z'den sonra gelir. Bu yüzden İzmir, Zonguldak'tan sonra listelenir.
MDN'ye göre Intl.Collator dile duyarlı karşılaştırma yapar ve sonuç dile göre değişir. MDN'nin örneğinde ä, Almancada a ile birlikte, İsveççede z'den sonra sıralanır. Türkçe için new Intl.Collator("tr").compare kullanın.
Testteki listede 10 yer adından 9'u iki sıralamada farklı yerde duruyor. Şehir seçici, müşteri listesi ya da filtre ve sıralama ekranı gibi A'dan Z'ye sıralanan her listede bunu kontrol ederim. Sıralama sunucuda yapılıyorsa veritabanının harmanlama (collation) ayarına da bakın.
Yazı tipi: ğ, ş, ı ve İ glifleri
Türkçe harflerin bir kısmı Unicode'da farklı bloklardadır. Ç, Ö ve Ü, Latin-1 Supplement bloğundadır (U+0080–U+00FF). Ğ, İ, ı ve Ş ise Latin Extended-A bloğundadır (U+0100–U+017F).
Bu fark yazı tipi seçerken önem kazanır. Latin-1 harflerini içerip Latin Extended-A bloğunu içermeyen bir yazı tipi Ç ve Ö'yü gösterir, ğ ve ş'yi göstermez. Tarayıcı eksik harfi başka bir yazı tipinden alır ve kelimenin ortasında farklı görünen bir harf belirir.
Web yazı tiplerini alt kümelere bölüyorsanız Türkçe harflerin hangi dosyada olduğuna bakın. Google Fonts belgeleri, Latin alt kümesinin varsa her zaman eklendiğini ve unicode-range destekleyen tarayıcıların gereken alt kümeleri kendisi seçtiğini yazar. Kendi sunucunuzdan yüklediğiniz dosyalarda ise bu seçim size kalır.
Benim test metnim kısadır: "Ilık İğdır, ŞÇÖÜ ğşıiçöü". Bunu tasarım dosyasında, kodda ve kalın yazı ağırlığında ayrı ayrı yazarım. Logo ve başlık yazı tiplerini de bu teste dahil ederim.
RTL yok, ama aynı kod tabanında olabilir
Türkçe soldan sağa yazılır. Arayüzü sağdan sola (RTL) çevirmeniz, ikonları aynalamanız ya da yönü tersine çevirmeniz gerekmez. Türkçe yerelleştirme bu konuda İngilizceyle aynı yerleşimi kullanır.
Ürününüz aynı kod tabanında Arapça gibi sağdan sola bir dili de destekliyorsa durum değişir. O iş bu rehberin konusu dışında. Benim tek önerim, yön bilgisini de dil gibi dir özniteliğiyle sayfaya vermeniz.
Benim notum
Türkçe hataları ararken çeviri dosyasından sonra bileşen koduna da bakarım. Çeviri doğru olabilir, ama metni büyük harfe çeviren CSS ya da tutara " TL" ekleyen bir yardımcı fonksiyon onu bozar. Bu yüzden yerelleştirmeyi tasarımdan koda geçişin bir parçası sayarım.
İşe en ucuz yerden başlarım. Kökte lang="tr", harf çevriminde "tr", biçimlerde Intl, sıralamada Collator. Bunlar birkaç satırlık değişikliklerdir ve çoğu ekranı aynı anda düzeltir.
Ses tonu kararı da yerelleştirmenin parçasıdır. Ürünün kullanıcıya "sen" mi "siz" mi diyeceğini çeviriye başlamadan seçin; bu konudaki görüşümü sen mi, siz mi yazısında anlattım. Karar bir kez verilip bütün metinlere uygulanırsa çeviri dosyası tutarlı kalır.
Türkçe sürümünüzü yeni kuruyorsanız ya da mevcut sürümdeki bu hataları temizlemek istiyorsanız, bunu Tasarla & Yayınla Sprinti içinde tasarım ve kodla birlikte yapabiliriz.
Sık sorulanlar
Yerelleştirme ile çeviri arasındaki fark ne?
Çeviri metni başka bir dile aktarır. Yerelleştirme ise metnin yanında tarih, sayı ve para biçimlerini, sıralamayı, harf kurallarını ve yerleşimi de hedef dile uyarlar. W3C, yerelleştirmenin çoğu zaman yalnızca arayüz ve belge çevirisiyle eş tutulduğunu yazar.
JavaScript'te Türkçe büyük harf nasıl yapılır?
toUpperCase() yerine toLocaleUpperCase("tr") kullanın. İlki "istanbul" kelimesini "ISTANBUL" yapar, ikincisi "İSTANBUL". Küçük harf için de toLocaleLowerCase("tr") kullanın. E-posta ve kullanıcı adı gibi teknik değerlerde ise dilden bağımsız çevrim kullanın.
CSS text-transform: uppercase Türkçede neden yanlış çıkıyor?
Tarayıcı dili lang özniteliğinden okur. Sayfada ya da ilgili öğede lang="tr" yoksa i harfi I olur. MDN'ye göre dile özgü harf desteği tarayıcıdan tarayıcıya değişir, bu yüzden sonucu gerçek cihazlarda kontrol edin.
Türkçe alfabetik sıralama nasıl yapılır?
Varsayılan sort() karakter kodlarına göre sıralar ve Ç, İ, Ş gibi harfleri Z'den sonraya atar. JavaScript'te liste.sort(new Intl.Collator("tr").compare) kullanın. Sıralama sunucuda yapılıyorsa veritabanının harmanlama ayarına da bakın.
Kaynaklar (11)
- W3C Internationalization, Text size in translation. erişim 2026-11-03; IBM'in uzama oranları tablosu, Almanca bileşik isim ve esnek yerleşim önerileri
- W3C Internationalization, Localization vs. Internationalization. erişim 2026-11-03; l10n ve i18n tanımları, kısaltmaların açıklaması
- MDN Web Docs, String.prototype.toLocaleUpperCase(). erişim 2026-11-03; istanbul örneği, uzunluk değişimi
- MDN Web Docs, text-transform. erişim 2026-11-03; Türkçe harf eşleşmeleri, lang özniteliği, tarayıcı desteği notu
- Unicode ICU User Guide, Formatting Messages. erişim 2026-11-03; select, other, mesajın en dış yapısı, kesme işareti
- MDN Web Docs, Intl.NumberFormat. erişim 2026-11-03; dile duyarlı sayı ve para biçimi
- MDN Web Docs, Intl.DateTimeFormat. erişim 2026-11-03; en-US ve en-GB tarih sırası örneği
- MDN Web Docs, Intl.Collator. erişim 2026-11-03; dile duyarlı karşılaştırma, Almanca ve İsveççe ä örneği
- Wikipedia, Latin Extended-A. erişim 2026-11-03; U+0100–U+017F, Ğ, İ, ı, Ş
- Wikipedia, Latin-1 Supplement. erişim 2026-11-03; U+0080–U+00FF, Ç, Ö, Ü
- Google Fonts, Get Started with the Google Fonts API. erişim 2026-11-03; alt kümeler ve unicode-range