Hreflang'da Dil mi Ülke mi Önce Tanımlanmalı: tr-TR mi TR-tr mi?

Hreflang etiketinde dil ve bölge kodu sırasının doğru kurulumunu temsil eden editoryal blog görseli

Hreflang etiketleri üzerine yeterince kaynak taradıysanız bir noktada şu soruyla karşılaşırsınız: dil kodu mu önce yazılır, bölge kodu mu? Sorunun kendisi bile bir belirsizlik taşıdığını gösteriyor; oysa cevap standart tarafında oldukça netleştirilmiş. Yine de TR-tr gibi ters çevrilmiş biçimlere gerçek sitelerin kaynak kodunda, hatta bazı toplu üretim scriptlerinde rastlamak mümkün.

Bu bir akademik merak konusu değil. Yüzlerce URL'yi otomatik hreflang setiyle besleyen bir sistemde sıra hatası tek bir satırda kalmaz; hreflang kümesinin sözdizimi şablondan yayılır; şablon veya değişken adı yanlış kurulmuşsa aynı hata tüm dil sürümlerine yayılır. Bir CMS eklentisinin çıktısında veya bir çeviri yönetim aracından dışa aktarılan listede bu tersine çevirme sessizce oluşabiliyor ve fark edilmeden yayına çıkabiliyor.

Bölge kodu eklenecekse nereye yazılacağı tartışmaya açık değildir. RFC 5646 dil alt etiketini birinci konuma koyar; Google aynı ayrıştırıcıyı kullanır. Büyük/küçük harf toleransı bu sıra kuralına taşınmaz; tr-tr işlenebilir, TR-tr yok sayılır.

RFC 5646 dil alt etiketini her zaman ilk sıraya koyar

BCP 47, dil etiketlerinin yapısını RFC 5646 üzerinden tanımlar ve bu yapı katmanlı bir sıralamaya sahiptir: birincil dil alt etiketi, isteğe bağlı genişletilmiş dil alt etiketi, isteğe bağlı yazı sistemi (script) alt etiketi, isteğe bağlı bölge alt etiketi, isteğe bağlı varyant alt etiketleri ve en sonda uzantılar. Bu sıra sabittir; hiçbir alt etiket kendisinden önce gelmesi gereken bir katmanın yerine geçemez.

Türkçe için pratikte bu katmanların büyük kısmı boş kalır; kullanılan yalnızca dil ve bölgedir. Ama sıra kuralı aynı şekilde işler: dil alt etiketi mutlaka birinci konumda durur, bölge alt etiketi mutlaka onu takip eder. tr-TR bu yapının doğru uygulanmış hâlidir: önce dil (tr), sonra bölge (TR).

Standardın mantığı şuna dayanır: dil, içeriğin okunabileceği en geniş kümeyi tanımlar; bölge bu kümenin içinde bir alt kırılım oluşturur. Bölge, dilden bağımsız var olamaz; her zaman bir dilin altında bir daraltma görevi görür. Dilin önce gelmesi tesadüf değil, bu hiyerarşinin çıktısıdır. Bölge kodunun eklenip eklenmeyeceği ayrı bir tasarım kararıdır; aynı dilde farklı ülkeler hedefleniyorsa bölge katmanı fiilen zorunlu hale gelir. Bu yazının konusu, eklendiyse konumudur.

"TR-tr" bu karışıklığın nereden geldiği

Ters sıra rastgele ortaya çıkmıyor; belirli kaynaklardan besleniyor. Birincisi, bazı çeviri yönetim platformları dil listelerini alfabetik sıralama kolaylığı için "Ülke - Dil" formatında dışa aktarır. Bir ekip bu tabloyu doğrudan kopyalayıp hreflang değeri olarak kullandığında sıra bozulmuş şekilde koda geçer.

İkincisi, programatik üretimde string birleştirme hatası. Bir geliştirici region + "-" + language şeklinde bir birleştirme yazdığında, kod çalışır, hata fırlatmaz, çıktı sözdizimsel olarak bir dil etiketine benziyor; ama sıra tersinedir. Bu tür hatalar test aşamasında genellikle fark edilmez çünkü çıktı "makul" görünür.

Üçüncüsü, coğrafi düşünme alışkanlığı. Bir pazarlama ekibi önce "hangi ülke" sorusunu sorar, sonra "hangi dil" sorusuna geçer. Bu zihinsel sıra, teknik uygulamaya dökülürken bazen doğrudan aktarılır: önce ülke kodu yazılır, ardından dil kodu eklenir. Karar süreci coğrafya odaklı olsa da, çıktı formatı bu odaklanmayı yansıtmak zorunda değildir.

Dördüncüsü, bazı sistem yerel ayarı (locale) gösterimleriyle karışma. İşletim sistemi veya ofis yazılımı arayüzlerinde bölge adının dil adından önce göründüğü listeler bulunur ("Türkiye - Türkçe" gibi görsel etiketler). Bu görsel sıralama, arka planda tutulan teknik koddan bağımsızdır; ama kullanıcı arayüzünde gördüğü sırayı hreflang koduna aktarma eğilimi doğurabiliyor.

Google dokümantasyonu ile RFC'nin ifadesi aynı noktada duruyor mu?

Google'ın hreflang uygulama kılavuzu, dil kodu için ISO 639-1'i, isteğe bağlı bölge kodu için ISO 3166-1 Alpha 2'yi referans alır ve format olarak dil-bölge sırasını gösterir. Bu, RFC 5646'nın tanımladığı sırayla birebir aynıdır; Google kendi başına farklı bir kural icat etmemiştir, mevcut standardı olduğu gibi kabul etmiştir.

Sık yapılan bir yanlış varsayım var: Google'ın kendi arama motoru altyapısında "daha esnek" bir yorumlama katmanı olduğu ve sıra hatalarını da tolere edebileceği düşüncesi. Gerçekte Google, hreflang değerlerini kendi özel bir ayrıştırıcıyla değil, BCP 47'ye uyumlu standart bir dil etiketi ayrıştırıcısıyla işler. Ayrıştırıcı bir etiketi geçersiz bulduğunda bunu "yorumlamaya çalışmaz", etiketi tanımadığı bir değer olarak bir kenara koyar.

Yani RFC ile Google dokümantasyonu arasında gerçek bir ayrışma yok; ikisi aynı sırayı tanımlıyor. Aralarında fark varmış gibi görünen tek yer, Google'ın bazı sözdizimi hatalarına gösterdiği tolerans ile ilgilidir; ama bu tolerans sıra kuralını değil, yazım biçimini (büyük/küçük harf, ayraç karakteri) kapsar. İki farklı toleranstan biri var, diğeri yok; ikisini aynı kefeye koymak yanlış bir genelleme üretiyor.

Ters sıra ("TR-tr") yazıldığında Google ne yapar?

Burada net bir ayrım kurmak gerekir: Google, TR-tr gördüğünde bunu "önce bölge sonra dil" şeklinde çözümleyip yine de doğru sayfayı eşleştirmeye çalışmaz. Ayrıştırıcı, ilk alt etiketin dil kodu olmasını bekler; ilk konumdaki TR değeri iki harfli olsa bile ISO 639-1 dil kodu listesinde geçerli bir karşılığa sahip değildir (büyük harfle yazılmış olması da ayrıca standarda aykırıdır). Sonuç, etiketin bütünüyle geçersiz sayılmasıdır; kısmi bir eşleştirme veya "tersten okuma" gerçekleşmez.

Pratik sonucu şudur: o hreflang değeri, o URL için hiç yazılmamış gibi davranılır; bu, hreflang hatalarını tespit ederken sözdizimi katmanında ayrı durur. Sayfa hreflang setinden fiilen düşer; başka bir dil sürümüyle karşılıklı referans kurulamaz, o dil için hedefleme sinyali oluşmaz. Bu, yanlış sayfanın gösterilmesi problemiyle aynı görünse de kök nedeni farklıdır; burada sorun bir sinyal çatışması değil, sinyalin hiç var olmamasıdır.

Search Console bu tür geçersiz kodları genellikle "desteklenmeyen dil kodu" veya benzeri bir uyarıyla raporlar. Ancak bu uyarı her zaman aynı netlikte gelmez; büyük bir URL setinde tek bir sayfadaki ters sıra hatası, toplam hata sayısı içinde kaybolabilir ve haftalarca fark edilmeyebilir.

Büyük-küçük harf toleransı sıra hatasını gizleyebilir

Google'ın dil kodunu küçük harf, bölge kodunu büyük harf beklemesi teknik olarak doğrudur; ama pratikte tr-tr (ikisi de küçük) veya TR-TR (ikisi de büyük) yazıldığında da çoğu durumda etiket işlenir, çünkü ayrıştırıcı büyük/küçük harf farkına karşı tolerans gösterir. Bu tolerans gerçektir ve yaygın olarak bilinir.

Sorun, bu bilginin genelleştirilmesinde ortaya çıkıyor. Bir geliştirici veya içerik ekibi "Google harf büyüklüğüne bakmıyor" bilgisini "Google format konusunda esnek" şeklinde geniş bir kurala dönüştürdüğünde, sıra hatasının da tolere edileceğini varsaymaya başlıyor. Bu varsayım yanlıştır ve tam da bu yanlışlık yüzünden ters sıra hataları üretim ortamına kadar fark edilmeden ilerleyebiliyor; "zaten esnek davranıyor" düşüncesiyle ekstra doğrulama adımı atlanıyor.

Harf büyüklüğü ve sıra, standardın iki ayrı katmanıdır. Biri yazım kuralına (case convention) aittir ve ayrıştırıcı tarafında normalize edilebilir. Diğeri yapısal sözdizimine (syntax structure) aittir ve normalize edilemez; çünkü ayrıştırıcının hangi konumda hangi tür alt etiket beklediğini belirleyen kural budur. Bir katmandaki gevşeklik, diğer katmandaki sıkılığı geçersiz kılmaz.

Toplu üretimde sıra hatası nasıl sisteme sızar?

Sıra hatası nadiren tek bir sayfada elle yazılan bir yazım yanlışı olarak ortaya çıkar; genellikle bir şablonun veya bir veri kaynağının içine gömülü olarak tüm sisteme yayılır. Üç yaygın giriş noktası vardır.

  • Şablon değişken sırası: Bir CMS şablonunda {{bolge}}-{{dil}} şeklinde tanımlanmış bir değişken dizisi, geliştiricinin "dil önce" diye düzenlemeyi unuttuğu durumlarda tüm sayfalara aynı hatalı sırayı yansıtır.
  • API veya feed kaynağı: Üçüncü parti bir çeviri servisinden veya ürün feed'inden gelen locale alanı "country_language" formatında geliyorsa ve bu alan doğrudan hreflang değerine dönüştürülüyorsa, kaynaktaki sıra hatası olduğu gibi sisteme taşınır.
  • Toplu bul-değiştir işlemleri: Büyük bir migration veya yeniden yapılandırma sürecinde regex tabanlı toplu düzenleme, dil ve bölge alt etiketlerinin yerini yanlışlıkla değiştirebilir; özellikle iki alt etiketin de iki harfli olduğu Türkçe gibi diller bu tür regex hatalarına daha açıktır.

Bu üç kaynağın ortak noktası, hatanın tek bir sayfada değil bir üretim mekanizmasında oturmasıdır. Dolayısıyla düzeltme de tek sayfa bazında değil, kaynağında yapılmalıdır; aksi halde bir sonraki içerik güncellemesinde veya yeni bir dil eklendiğinde hata yeniden üretilir. Üretim şablonunda dil ve bölge kodunu doğru sırayla üretmek bu kaynağı tek bir sıraya kilitler.

Doğrulama tarafında en güvenilir yöntem, yayına çıkmadan önce hreflang değerlerini basit bir düzenli ifadeyle (regex) kontrol etmektir: ilk iki karakterin küçük harf bir dil kodu deseniyle, varsa sonraki iki karakterin büyük harf bir bölge kodu deseniyle eşleşip eşleşmediğini otomatik kontrol eden bir adım, sıra hatasını insan gözünden çok daha güvenilir yakalar. Search Console'un uluslararası hedefleme raporu bu tür hataları geriye dönük yakalayabilir; ama yayın öncesi bir doğrulama adımı, hatayı hiç üretime sokmadan önler.

"Dil mi ülke mi önce yazılır" sorusunun cevabı tartışmaya açık değil; RFC 5646 ve Google'ın kendi dokümantasyonu tam olarak örtüşüyor, dil her zaman ilk sıradadır. Asıl karar verilmesi gereken yer, bölge kodunun etikete eklenip eklenmeyeceğidir; bu, sıradan bağımsız, ayrı bir tasarım kararıdır.

Sıra hatasının tehlikeli yanı, sözdizimsel olarak "makul" görünmesidir; bir geliştirici veya editör TR-tr yazısını gördüğünde bunun hatalı olduğunu gözle ayırt etmesi zordur, çünkü iki harf de doğru karakterlerden oluşur. Bu yüzden görsel denetim yerine otomatik format kontrolüne güvenmek, büyük ölçekli hreflang setlerinde tek gerçek güvence hâline geliyor.