İçeriğe geç
wedevit

25 Ağustos 2026 · 9 dk okuma · yazılım

İlhan Buğra Aslan

Çok dilli site nasıl kurulur? URL yapısı, hreflang ve çeviriden sonra kalan iş


Çok dilli bir site üç ayrı iştir ve genelde yalnızca biri planlanır. Birincisi adresleme: her dil kendi kalıcı URL'sinde durur, dil kurabiyeye ya da tarayıcı ayarına göre değişmez. İkincisi arama motoruna hangi sayfanın hangisinin karşılığı olduğunu anlatmak, yani karşılıklı hreflang etiketleri ve x-default. Üçüncüsü çeviri bittikten sonra kalan iş: çoğul kuralları, tarih ve para biçimi, sıralama, büyük-küçük harf dönüşümü, arayüzde uzayan metin. Bütçe genelde ikinci ve üçüncü kalemi hiç görmez, o yüzden site çevrilmiş görünür ama yanlış çalışır.

Her dil kendi URL'sinde durmalı

Aynı adreste dili değiştiren siteler tek bir sebeple başarısız olur: o adreste birden fazla sürüm yoktur, tek bir sürüm vardır ve o sürüm ziyaretçiye göre şekil değiştirir. Google'ın kendi dokümanı dili nasıl belirlediğini net yazıyor: hreflang ya da HTML lang niteliği dil tespiti için kullanılmıyor, dil sayfanın görünür içeriğinden algoritmayla çıkarılıyor. Yani tarayıcı ayarına ya da kurabiyeye bakarak içerik değiştiren bir sayfada Googlebot yalnızca kendisine sunulan varyantı görür, diğerleri hiç var olmaz.

İkinci sorun tarama tarafında bile değil, insan tarafında. Türkçe sayfayı okuyan biri bağlantıyı Alman iş ortağına gönderdiğinde karşı taraf kendi diline düşmez, sizin oturumunuzun diline düşer. Konum ya da Accept-Language başlığına bakıp otomatik yönlendirme yapmak da çözüm değil; Google bu uygulamaya karşı açıkça uyarıyor, çünkü otomatik yönlendirme hem kullanıcıların hem arama motorlarının bütün sürümleri görmesini engelliyor. Çalışan desen şu: dil seçici her sayfada görünür olsun, ilk ziyarette "İngilizce sürüme geçmek ister misiniz?" gibi kapatılabilir bir bant çıksın, seçim hatırlansın, ama adres kullanıcı tıklamadan değişmesin.

Alt dizin, alt alan adı, ayrı ülke alan adı

Google üç yapıyı da destekliyor ve aralarındaki farkı kendi dokümanında karşılaştırıyor. Ülke alan adı (ornek.de) en açık coğrafi sinyali verir, sunucu konumundan bağımsızdır, karşılığında her alan adı ayrı bir varlıktır: ayrı tescil, ayrı sertifika, ayrı bağlantı profili, ayrı yönetim yükü. Alt alan adı (de.ornek.com) kurulumu kolaydır ama kullanıcı için sinyali zayıftır. Alt dizin (ornek.com/de/) bakımı en ucuz seçenektir ve tek alan adında biriken otoriteyi paylaşır; coğrafi sinyali en belirsiz olanıdır. URL parametresi (ornek.com?lang=de) Google'ın doğrudan önermediği tek yöntem.

Pratikte tek pazarlama sitesi olan şirketlerin çoğu için alt dizin doğru cevap. Ayrı ülke alan adı, o ülkede ayrı bir tüzel varlığınız, ayrı fiyat listeniz ve o alan adını besleyecek ayrı bir içerik planınız varsa mantıklı. Bir de artık geri dönüşü olmayan bir ayrıntı var: Search Console'un ülke hedefleme ayarı içeren Uluslararası Hedefleme raporu Ağustos 2022'de kullanımdan kaldırıldığını duyurdu ve Eylül 2022'de arayüzden çıktı. Yani "panelden ülke seçeriz" diye bir telafi yok, yapı ve içerik ne söylüyorsa o geçerli.

Slug da içeriğin parçası

Türkçe sayfaya İngilizce adres vermek yaygın ve gereksiz bir kayıp. Kullanıcı adresin ne anlattığını okuyamaz, arama sonucunda görünen URL parçası dilden düşer, paylaşılan bağlantı yabancı durur. Doğru ayrım şu: dosya ya da çeviri anahtarı teknik bir kimliktir, URL ise okuyucuya gösterilen içeriktir. Aynı yazının Türkçesi /tr/blog/cok-dilli-site-url-yapisi-hreflang adresinde, İngilizcesi /en/blog/multilingual-site-architecture adresinde durabilir ve hreflang bu ikisini birbirine bağlar.

Türkçe slug yazarken Türkçe karakter kullanmayın. ş, ı, ğ, ü, ö, ç adres çubuğunda çalışır, ama kopyalanıp yapıştırıldığında yüzde kodlamasına dönüşür ve okunaksız bir dizeye çıkar. ASCII karşılıklarına indirgeyin, tireyle ayırın, kısa tutun.

hreflang: kural sayısı az, tolerans sıfır

Etiket üç yerde durabilir: HTML <head> içinde link etiketi, HTML olmayan dosyalar için HTTP Link başlığı, ya da site haritasında xhtml:link alt öğesi. Üçü de eşdeğer. Yüzlerce sayfası olan sitelerde site haritası genelde daha bakımı kolay çıkıyor, çünkü eşleşme tek bir dosyada durur.

Kurallar kısa ve esnemiyor:

  • Her sayfa kendisi dahil bütün varyantları listeler.
  • Bağlantı karşılıklı olmak zorunda. Google'ın ifadesi net: iki sayfa birbirini göstermiyorsa etiketler yok sayılır. Tek yönlü hreflang hiçbir işe yaramaz.
  • Dil kodu ISO 639-1, isteğe bağlı olarak ISO 3166-1 alpha-2 bölge kodu eklenir: tr, en, en-GB, de-CH. Ülke kodunu tek başına yazamazsınız, ilk parça dil olmak zorunda.
  • x-default hiçbir dil eşleşmediğinde gidilecek adresi işaret eder. Dil seçici sayfası ya da ana sürüm için uygundur.
  • Hatalı etiket ceza getirmez, sadece dikkate alınmaz. Bu iyi haber gibi görünür, kötü haberdir: bozulduğunda hiçbir uyarı almazsınız.

Denetimi kim yapacak sorusunun cevabı da 2022'de değişti. Uluslararası Hedefleme raporu kalktığı için hreflang hatalarını Search Console'da göremiyorsunuz; bu iş artık site tarayıcı araçlarına ya da kendi yayın hattınıza yazacağınız bir kontrole kaldı. Dil sürümlerinden biri silindiğinde ya da adresi değiştiğinde karşı taraftaki etiketin de güncellendiğini doğrulayan bir test, tek başına bu işin yarısını çözüyor.

Dil sürümü mü, pazar sürümü mü

en-GB ve en-US ayırmak çoğu şirket için gereksiz iki katı iş demek. Bölgesel varyant, ancak fiyat, para birimi, teslimat koşulu, stok ya da yasal metin gerçekten farklıysa anlamlı. Bu farklar yoksa iki sayfa neredeyse birebir aynı olur, ikisi de aynı sorguya girer ve siz kendi sayfalarınızla yarışırsınız. Tek bir en sürümü tutmak, sonradan gerçek bir pazar farkı doğduğunda bölmek daha ucuz.

Aynı soru dil seçiminde de geçerli. Üç dil eklemek, üç kat içerik değil, üç kat içerik operasyonu demek: her yeni sayfa, her fiyat güncellemesi, her kampanya metni artık üç yerde yaşıyor. Bir dili iyi taşımak, üç dili yarım taşımaktan her ölçüde daha iyi sonuç veriyor.

Makine çevirisi nerede biter

Google'ın spam politikalarında Mart 2024'te devreye giren "ölçekli içerik kötüye kullanımı" maddesi bu konuda açık. Politikanın örnek listesinde şu var: besleme, arama sonucu ya da başka içerikleri kazıyıp çok sayıda sayfa üretmek, buna eş anlamlılaştırma ve çeviri gibi otomatik dönüşümler de dahil, kullanıcıya az değer sağlanıyorsa. Politika yönteme değil sonuca bakıyor; içeriği insanın mı yoksa modelin mi ürettiği tek başına belirleyici değil, sayfanın kullanıcıya bir karşılığı olup olmadığı belirleyici.

Uygulamada bu, makine çevirisini yasaklamıyor, denetimsiz toplu çeviriyi yasaklıyor. Çalışan yöntem, makine çevirisinin üzerine insan düzeltmesi koymak ve bunu her sayfaya değil önceliğe göre yapmak: satış yapan sayfalar, fiyat ve sözleşme metinleri, teknik dokümantasyonun sık okunan bölümleri önce. Bir de terim sözlüğü tutun. Ürün adları, modül isimleri ve sektör terimleri her çeviride aynı karşılığa düşmezse, aynı özelliğin üç sayfada üç farklı adı olur ve arama tarafında hiçbiri toparlanmaz. Yapay zekâ destekli aramada nasıl göründüğünüz ayrı bir konu, onu yapay zeka aramada görünürlük yazısında ele almıştık.

Çeviri bitti, yerelleştirme yeni başlıyor

Metinler koddan ayrılmadıysa geri kalan her şey pahalıya patlar. Temel kural, arayüzdeki her dizeyi bir anahtar altında tutmak ve cümleyi parçalardan birleştirmemek. "Toplam " + n + " kayıt bulundu" biçiminde kurulan bir cümle, kelime sırası farklı olan bir dilde onarılamaz. Bunun standart çözümü ICU MessageFormat: değişkenler, çoğul ve cinsiyet dallanmaları tek bir şablonun içinde durur.

Çoğul tarafı sanıldığından karmaşık. Unicode CLDR altı çoğul kategorisi tanımlıyor: zero, one, two, few, many, other. Her dil bunların bir alt kümesini kullanıyor; Arapça altısını birden kullanırken Türkçe ve İngilizce ikiyle yetiniyor. Türkçe'de ayrıca sayıdan sonra çoğul eki gelmez: "3 kitap" doğru, "3 kitaplar" değil. İngilizce şablondan birebir üretilmiş bir çoğul kuralı bunu bilmez. Tarih, saat ve para birimi için elle biçimlendirme yazmayın; ECMA-402'nin Intl API'si bu işi CLDR verisiyle yapıyor. Zaman damgalarını sunucuda UTC saklayıp gösterimde yerelleştirmek de aynı ailenin kuralı.

Türkçe'nin kendine has tuzağı: noktasız ı

Türkçe'de I harfinin küçüğü ı, i harfinin büyüğü İ. Bu, dünyanın en çok bilinen yerelleştirme hatalarından birini üretir. Java'nın kendi dokümanı örneği veriyor: Türkçe yerel ayarında "TITLE".toLowerCase() sonucu "tıtle" çıkar ve dil bağımsız sonuç isteyen kod için toLowerCase(Locale.ROOT) önerilir. .NET tarafında ToLower() varsayılan olarak kültüre duyarlıdır. JavaScript'te durum tersine kurgulanmış: toLowerCase() yerelden bağımsızdır, yereli hesaba katan toLocaleLowerCase() metodudur.

Kural basit: kullanıcıya gösterilecek metinde yerele duyarlı dönüşüm kullanın, karşılaştırmada kullanmayın. Kullanıcı adı, e-posta, dosya uzantısı, HTTP başlığı, önbellek anahtarı ve yetki kontrolü gibi yerlerde dönüşüm dilden bağımsız olmalı. Aksi halde uygulamanız Türkçe yerel ayarlı bir sunucuda İngilizce sunucudakinden farklı davranır ve bu hata testlerde neredeyse hiç görünmez.

İkinci kısım sıralama ve arama. Alfabetik sıra dile göre değişir, ç ve ş gibi harflerin yeri sabit değildir. MySQL 8 tarafında utf8mb4_tr_0900_ai_ci gibi dile özel harmanlamalar var; PostgreSQL 10'dan beri ICU harmanlamalarını destekliyor ve dil bazlı sıralamayı buradan alabiliyorsunuz. Arama kutusunda da beklenti nettir: "Istanbul" yazan kullanıcı "İstanbul" kaydını bulmalı. Bunu sağlarken kurduğunuz normalizasyonun indeksi kullanılamaz hale getirmediğini kontrol edin, yoksa çok dilli arama sessizce yavaş sorgu üretmeye başlar.

Arayüz: metin uzar, bazen yön değişir

Çeviri metni büyütür. W3C'nin aktardığı IBM tablosuna göre 10 karaktere kadar olan kısa İngilizce dizelerde beklenen genişleme %200 ile %300 arasında, 70 karakterin üzerindeki metinlerde %130'a iniyor. Kısa metin en çok genişleyendir ve kötü haber şu ki kısa metin genelde en dar yerde durur: buton içi, sekme, form etiketi, ikon yanı. Sabit genişlikli bir buton İngilizce'de düzgün, Almanca'da taşmış görünür.

Test etmenin ucuz yolu sahte yerelleştirme. Dizeleri otomatik uzatıp aksanlı karakterlerle işaretleyen bir yerel ayar oluşturursunuz, arayüzü onunla açarsınız ve hem taşan kutuları hem de çeviriye hiç açılmamış sabit metinleri tek geçişte görürsünüz. Arapça ya da İbranice hedefteyse iş bir katman daha derinleşir: dir="rtl", margin-left yerine margin-inline-start gibi mantıksal CSS özellikleri, yön bildiren ikonların aynalanması.

Yarım çeviri, en pahalı hâli

Çok dilli sitelerin çoğu ilk gün değil, altıncı ayda bozulur. Türkçe tarafa yeni bir sayfa eklenir, İngilizcesi "sonra yapılır" diye beklemeye alınır, o sayfa hiçbir hreflang kümesine girmez ve arada kalır. Bir süre sonra iki dil arasındaki fark, hangi bilginin güncel olduğunu kimsenin bilemeyeceği bir seviyeye çıkar.

Bunu önleyen kural tek cümle: çevirisi tamamlanmamış sayfa yayına girmez, girecekse noindex ile girer ve dil eşleme kümesine dahil edilmez. Yanına da bir sahip yazın. Çeviri belleği ve terim sözlüğünü kim tutuyor, yeni sayfanın çeviri talebini kim açıyor, kaynak metin değiştiğinde çevirinin bayatladığını hangi kontrol söylüyor? Bir de erişilebilirlik tarafını unutmayın: html etiketindeki lang niteliği WCAG 2.2'de A seviyesi bir başarı ölçütüdür, Google dil tespitinde kullanmasa da ekran okuyucular telaffuzu ona göre seçer, sayfa içinde dil değişen bölümlerde de ayrıca işaretlenmesi gerekir (WCAG 2.2 uyumu).

Bu haftaya sığan ilk adım

Beş kontrol yapın. Bir: her dil sürümünün kendi kalıcı URL'si var mı, yoksa dil kurabiyeye mi bağlı? İki: iki sayfa da birbirini gösteren hreflang etiketi taşıyor mu, x-default tanımlı mı? Üç: konuma göre otomatik yönlendirme var mı, varsa yerine kapatılabilir bir öneri bandı koyabilir misiniz? Dört: tarih, para ve çoğul biçimleri hedef dilde doğru mu, arayüzde taşan kutu var mı? Beş: yayında çevirisi eksik kaç sayfa duruyor ve bunların dizine girmesi engellenmiş mi?

Bu beş maddenin dördü bir günlük iş, biri kalıcı bir süreç. Sıra da bu: önce adresleme ve eşleme düzelsin, sonra çeviri operasyonuna bir sahip atansın. Yeni dilin sayfa hızını da ayrıca ölçün, çünkü uzak bir pazara hizmet veren site kendi ülkenizdeki ölçümlerle aynı sonucu vermez (Core Web Vitals ve gerçek kullanıcı verisi).


Bu konuda yardıma mı ihtiyacınız var?

iletişime geçtüm yazılar