---
title: Uluslararasılaştırma
source: 'https://academia.sh/tr/kurslar/frontend-mimarisi/uluslararasilastirma'
course: 'Uygulama Mimarisi: Yönlendirme, Durum ve Veri'
language: tr
updated: '2026-08-17T18:09:20+00:00'
license: 'CC BY-SA 4.0'
---

# Uluslararasılaştırma

Metnin koddan ayrılması, çeviri kataloğu ve anahtar tasarımı, çoğul kurallarının dile göre değişmesi, biçimlemenin platforma bırakılması, yön desteği ve yerel ayarın seçilmesi.

Kimlik akışı tamamlandı: gözlemci tanınıyor, oturumu kendiliğinden sürüyor. Ama tanınan
gözlemcinin bir de dili var. Bu kurs boyunca üretilen her metin tek bir dile göre yazıldı —
hata iletileri, "oturum düştü" bildirimi, boş sonuç açıklamaları. Sayılar ve tarihler de
öyle: ölçüm değeri "−4,2" biçiminde yazıldı, tarih gün-ay-yıl sırasıyla gösterildi.

Kuzey Yamaç istasyonunu başka bir ülkeden izleyen bir gözlemci için bunların hiçbiri doğru
değil. Bu ders arayüzü dile ve bölgeye uyarlanabilir kılmanın yapısını kurar.

## İki Ayrı İş

**Uluslararasılaştırma (internationalization)**, uygulamayı uyarlanabilir hâle getirmektir:
metinlerin koddan ayrılması, biçimlemenin sabitlenmemesi, düzenin yön değişimine dayanması.
Bir kez yapılır ve dilden bağımsızdır.

**Yerelleştirme (localization)**, belirli bir dil ve bölge için içeriğin üretilmesidir:
çevirilerin yazılması, tarih ve para biriminin o bölgeye uygun seçilmesi. Her dil için
ayrı yapılır.

Ayrımın pratik değeri sıradadır. Uluslararasılaştırma yapılmamış bir uygulamaya çeviri
eklemek, kodun her yerine dokunmayı gerektirir. Yapılmış bir uygulamaya ikinci dili eklemek
yalnız bir katalog dosyası yazmaktır. Bu yüzden tek dilli kalacağı düşünülen uygulamalarda
bile metnin koddan ayrılması ucuz bir yatırımdır.

## Çeviri Kataloğu ve Anahtar Tasarımı

**Çeviri kataloğu**, anahtarları iletilere eşleyen bir yapıdır. Kod anahtarı bilir, metni
bilmez.

Anahtarın kendisi bir tasarım kararıdır. Anahtar olarak Türkçe cümleyi kullanmak — "2 alan
düzeltilmeli" — kolay görünür ama metin her düzeltildiğinde bütün çeviriler kopar. Anlamı
tanımlayan yapılandırılmış bir ad — `form.ozet` — bu bağı korur. Aynı sözcüğün iki yerde
farklı çevrilmesi gerekebileceği için anahtar bağlamı da taşır: `dugme.kaydet` ile
`menu.kaydet` ayrı anahtarlardır, ikisi de Türkçede "Kaydet" olsa bile.

```js
// ceviri-katalogu.mjs — anahtar, yer tutucu ve cogul kurallari
const KATALOG = {
  tr: {
    "form.ozet": { one: "{sayi} alan düzeltilmeli", other: "{sayi} alan düzeltilmeli" },
    "olcum.aralik": "{enAz} ile {enCok} arasında bir değer girin.",
    "oturum.dustu": "Oturumunuz sona erdi.",
  },
  en: {
    "form.ozet": { one: "{sayi} field needs attention", other: "{sayi} fields need attention" },
    "olcum.aralik": "Enter a value between {enAz} and {enCok}.",
  },
};

const VARSAYILAN = "tr";

function ileti(dil, anahtar, degiskenler = {}) {
  const girdi = KATALOG[dil]?.[anahtar] ?? KATALOG[VARSAYILAN]?.[anahtar];
  if (girdi === undefined) return `!${anahtar}`;   // eksik anahtar gizlenmez
  const kalip = typeof girdi === "string"
    ? girdi
    : girdi[new Intl.PluralRules(dil).select(degiskenler.sayi)] ?? girdi.other;
  return kalip.replace(/\{(\w+)\}/g, (tam, ad) =>
    ad in degiskenler ? String(degiskenler[ad]) : tam);
}

console.log("çoğul kategorileri (Intl.PluralRules)");
console.log("sayı".padEnd(6) + ["tr", "en", "ru"].map((d) => d.padEnd(8)).join(""));
for (const sayi of [0, 1, 2, 5, 11, 21, 100]) {
  console.log(String(sayi).padEnd(6) +
    ["tr", "en", "ru"].map((d) => new Intl.PluralRules(d).select(sayi).padEnd(8)).join(""));
}

console.log("\niletiler");
for (const dil of ["tr", "en"]) {
  for (const sayi of [1, 2]) {
    console.log(`  ${dil} sayi=${sayi}: ${ileti(dil, "form.ozet", { sayi })}`);
  }
  console.log(`  ${dil} aralık : ${ileti(dil, "olcum.aralik", { enAz: -60, enCok: 60 })}`);
  console.log(`  ${dil} oturum : ${ileti(dil, "oturum.dustu")}`);
  console.log(`  ${dil} eksik  : ${ileti(dil, "olcum.bilinmeyen")}`);
}
```

```
çoğul kategorileri (Intl.PluralRules)
sayı  tr      en      ru      
0     other   other   many    
1     one     one     one     
2     other   other   few     
5     other   other   many    
11    other   other   many    
21    other   other   one     
100   other   other   many    

iletiler
  tr sayi=1: 1 alan düzeltilmeli
  tr sayi=2: 2 alan düzeltilmeli
  tr aralık : -60 ile 60 arasında bir değer girin.
  tr oturum : Oturumunuz sona erdi.
  tr eksik  : !olcum.bilinmeyen
  en sayi=1: 1 field needs attention
  en sayi=2: 2 fields need attention
  en aralık : Enter a value between -60 and 60.
  en oturum : Oturumunuz sona erdi.
  en eksik  : !olcum.bilinmeyen
```

Çoğul tablosu, elle yazılan bir çoğul kuralının neden yetmediğini gösteriyor. Türkçede ve
İngilizcede iki kategori var ve `sayi === 1` sınaması ikisinde de doğru sonucu verir.
Rusçada dört kategoriden üçü bu tabloda görünüyor ve seçim yalnız sayının kendisine değil
son basamağına da bağlı: 21 "one" kategorisine düşerken 11 "many" kategorisinde kalıyor.
Kuralı elle yazan kod, üçüncü dil eklendiğinde yeniden yazılır. `Intl.PluralRules` kuralı
dilden okur; katalog yalnız hangi kategoride ne yazılacağını söyler.

Türkçenin iki biçiminin aynı metni taşıması bir tutarsızlık değil. Katalog **yapıyı**
korur; hangi dilin kaç biçim kullandığı o dilin kararıdır. Aynı katalog Rusçaya
eklendiğinde `few` ve `many` anahtarları da yazılır, kod değişmez.

İki davranış daha çıktıda görünüyor. **Eksik anahtar gizlenmiyor**: bulunmayan bir anahtar
için ünlem işaretli bir gösterim üretiliyor. Boş dizgi döndürmek ya da anahtarı sessizce
atlamak, eksik çeviriyi görünmez kılar ve sürüm sonrası fark edilir. **Eksik çeviri
varsayılan dile düşüyor**: İngilizce katalogda bulunmayan oturum iletisi Türkçe geldi.
Bu, eksik metnin hiç görünmemesinden iyidir ama bir uyarı işaretidir; geliştirme sırasında
kaydedilmelidir.

Son bir kural: **iletiler dizgi birleştirmesiyle kurulmaz**. "Toplam " + sayi + " kayıt"
biçiminde yazılan bir metin, sözcük sırası farklı bir dile çevrilemez. Parçalar tek bir
kalıpta ve yer tutucuyla durur.

## Biçimlemeyi Platforma Bırakmak

Metin dışındaki her şey — sayı, tarih, süre, liste, sıralama — dile ve bölgeye göre
değişir ve bu kuralların hepsi platformda hazır bulunur.

```js
// bicimleme.mjs — sayi, tarih, liste ve siralamanin yerel ayara bagliligi
const DILLER = ["tr", "en-US", "de-DE"];
const OLCUM = -4.2;
const AN = new Date("2026-01-14T06:00:00Z");     // sabit an: cikti yeniden uretilebilir

console.log("sıcaklık (birimle)");
for (const d of DILLER) {
  console.log("  " + d.padEnd(6) +
    new Intl.NumberFormat(d, { style: "unit", unit: "celsius",
      minimumFractionDigits: 1 }).format(OLCUM));
}

console.log("büyük sayı");
for (const d of DILLER) {
  console.log("  " + d.padEnd(6) + new Intl.NumberFormat(d).format(1840.5));
}

console.log("tarih ve saat (UTC)");
for (const d of DILLER) {
  console.log("  " + d.padEnd(6) + new Intl.DateTimeFormat(d, {
    dateStyle: "long", timeStyle: "short", timeZone: "UTC" }).format(AN));
}

console.log("göreli zaman (-3 saat)");
for (const d of DILLER) {
  console.log("  " + d.padEnd(6) +
    new Intl.RelativeTimeFormat(d, { numeric: "auto" }).format(-3, "hour"));
}

console.log("liste");
const istasyonlar = ["Kuzey Yamaç", "Sırt", "Vadi"];
for (const d of DILLER) {
  console.log("  " + d.padEnd(6) +
    new Intl.ListFormat(d, { style: "long", type: "conjunction" }).format(istasyonlar));
}

// --- Turkce'ye ozgu iki tuzak ----------------------------------------------
const ADLAR = ["Ordu", "Ödemiş", "Osmaniye", "Sivas", "Şile", "Isparta", "İstanbul"];
console.log("\nsıralama");
console.log("  tr    " + [...ADLAR].sort(new Intl.Collator("tr").compare).join(", "));
console.log("  en    " + [...ADLAR].sort(new Intl.Collator("en").compare).join(", "));
console.log("  ham   " + [...ADLAR].sort().join(", "));

console.log("büyük harfe çevirme");
console.log("  tr    " + "ilk ölçüm".toLocaleUpperCase("tr"));
console.log("  en    " + "ilk ölçüm".toLocaleUpperCase("en"));
```

```
sıcaklık (birimle)
  tr    -4,2°C
  en-US -4.2°C
  de-DE -4,2 °C
büyük sayı
  tr    1.840,5
  en-US 1,840.5
  de-DE 1.840,5
tarih ve saat (UTC)
  tr    14 Ocak 2026 06:00
  en-US January 14, 2026 at 6:00 AM
  de-DE 14. Januar 2026 um 06:00
göreli zaman (-3 saat)
  tr    3 saat önce
  en-US 3 hours ago
  de-DE vor 3 Stunden
liste
  tr    Kuzey Yamaç, Sırt ve Vadi
  en-US Kuzey Yamaç, Sırt, and Vadi
  de-DE Kuzey Yamaç, Sırt und Vadi

sıralama
  tr    Isparta, İstanbul, Ordu, Osmaniye, Ödemiş, Sivas, Şile
  en    Isparta, İstanbul, Ödemiş, Ordu, Osmaniye, Şile, Sivas
  ham   Isparta, Ordu, Osmaniye, Sivas, Ödemiş, İstanbul, Şile
büyük harfe çevirme
  tr    İLK ÖLÇÜM
  en    ILK ÖLÇÜM
```

Bu çıktı **ortama bağlıdır**: biçimlerin ayrıntısı çalışma zamanının içerdiği yerel ayar
verisinin sürümüne göre değişebilir. Yukarıdaki satırlar `node --version` çıktısı v24.18.0
olan bir kurulumda üretildi. Değişebilen şey biçimin ayrıntısıdır; ilkeler değişmez.

Beş gözlem çıkarılır.

**Ondalık ayırıcı ve binlik ayırıcı dile göre yer değiştirir.** Türkçe ve Almanca virgülle
ondalık yazar, İngilizce noktayla. Sayıyı elle biçimleyen kod bunu kaçırır ve "1.840,5"
değerini "1840.5" diye gösterir; daha kötüsü, kullanıcının yazdığı "1,5" değerini yanlış
okur. Form doğrulama şemasındaki virgül–nokta dönüşümünün nedeni buydu.

**Birimin metne yapışması bile dile bağlıdır.** Almanca çıktıda sayı ile derece işareti
arasında boşluk var, Türkçede yok.

**Tarih sırası ve ay adı değişir; saat biçimi de değişir.** İngilizce çıktıda on iki saatlik
gösterim, diğerlerinde yirmi dört saatlik. Zaman dilimi ayrıca verilmelidir; örnekte UTC
sabitlendiği için çıktı yeniden üretilebilir.

**Liste birleştirme dilbilgisidir.** Türkçede son ögeden önce "ve", İngilizcede virgül ve
"and", Almancada "und" gelir. Elle virgül koyup sonuncudan önce bağlaç eklemek her dilde
ayrı bir kural demektir.

**Sıralama ve harf dönüşümü Türkçede özel durumdur.** Ham sıralama kod noktası sırasını
verir ve Türkçe alfabeye hiç uymaz. Türkçe sıralamada `O` ile `Ö`, `S` ile `Ş` ayrı
harflerdir ve bu sırayla dizilir; İngilizce sıralamada aynı harfin çeşitleri sayılırlar,
bu yüzden "Ödemiş" iki listede farklı yerde durur. Harf dönüşümünde de `i` harfinin büyüğü
Türkçede `İ`, diğer dillerde `I`'dır; yerel ayar verilmeden yapılan bir dönüşüm, çalıştığı
makinenin ayarına göre değişen sonuç üretir.

## Yön Desteği

Sağdan sola yazılan diller yalnız metnin değil düzenin de yön değiştirmesini gerektirir.
İş üç düzeyde ayrılır.

**Belge düzeyi.** Kök ögede yön bildirilir; yön bilgisi bir dil özelliği değil bir yazım
sistemi özelliğidir, bu yüzden dil bildiriminden ayrı verilir. Yön değiştiğinde metnin
hizası, listelerin madde işareti tarafı ve kaydırma yönü kendiliğinden döner.

**Düzen düzeyi.** CSS ile Görsel Sunum kursunda tanıtılan mantıksal kenar adları burada
karşılığını bulur: sol ve sağ yerine blok ve satır içi eksenin başlangıç ve bitiş
kenarları yazıldığında düzen yön değişimine kendiliğinden uyum sağlar. Fiziksel yönle
yazılmış her kural, yön desteği eklenirken tek tek gözden geçirilmelidir.

**Metin düzeyi.** Karışık yönlü metin — sağdan sola bir cümlenin içinde soldan sağa bir
istasyon kodu — özel bir sorun çıkarır: sıralama algoritması sınırdaki noktalama
işaretlerini yanlış tarafa taşıyabilir. Kullanıcıdan gelen ya da veriden gelen bir parçanın
çevresindeki metinden yalıtılması gerekir; işaretlemede bunun için ayrılmış bir öge vardır
ve bu ögenin varsayılan yön kestirimi parçanın kendi içeriğine bakar.

Simgelerin bir kısmı da yönlüdür: ileri oku, geri oku, girinti işaretleri yön değişiminde
aynalanır. Saat yönü, ses düzeyi gibi yönü olmayan simgeler aynalanmaz.

## Yerel Ayarın Seçilmesi ve Kataloğun Yüklenmesi

Hangi dilin kullanılacağı üç kaynaktan gelir ve öncelik sırası bellidir. **Kullanıcının
açık tercihi** en üsttedir ve saklanır. Yoksa **adresin kendisi** — dil kodunu taşıyan bir
yol parçası ya da alt alan adı — kullanılır; bu, bağlantının paylaşılabilir olmasını
sağlar. İkisi de yoksa tarayıcının bildirdiği dil listesi, yani `Accept-Language` başlığı
değerlendirilir.

Tarayıcının listesi bir sıralı tercihtir, tek bir dil değildir. Eşleme yaparken tam
eşleşme aranır, bulunamazsa bölge düşürülerek denenir; hiçbiri tutmazsa varsayılan dile
düşülür. Yerel ayar bir dilden fazlasını içerir — bölge, takvim, sayı sistemi — bu yüzden
metin dili ile biçimleme ayarının farklı olabileceği durumlar vardır.

Katalog yüklemesi bir paketleme kararıdır. Bütün dilleri tek pakette göndermek, kullanıcıya
kullanmayacağı metinleri indirtir. Dil başına ayrı bir parça üretip yalnız seçilen dili
yüklemek doğru yoldur; bu, Oluşturma Stratejileri kursundaki kod bölme konusuyla doğrudan
ilişkilidir. Dil değiştiğinde yeni katalog yüklenene kadar geçen sürede arayüzün ne
göstereceği — eski dil mi, boşluk mu — Yükleme ve Hata Durumları dersindeki durum
makinesine bağlanır.

Son olarak, çeviri metinleri **yer kaplar**. Aynı cümle bir dilde diğerinden belirgin
biçimde uzun olabilir; sabit genişlikli düğmeler ve tek satıra sığdırılmış etiketler
çeviriyle taşar. Düzenin metin uzunluğuna dayanması bir uluslararasılaştırma gereğidir.

## Özet

- Uluslararasılaştırma uygulamayı uyarlanabilir kılar ve bir kez yapılır; yerelleştirme her
  dil için ayrı üretilen içeriktir.
- Çeviri kataloğu anlamı tanımlayan yapılandırılmış anahtarlar kullanır; kaynak cümleyi
  anahtar yapmak, metin düzeltildiğinde bütün çevirileri koparır.
- Çoğul kategorileri dile göre değişir ve sayının son basamağına bağlı olabilir; kural
  platformdan okunur, katalog yalnız kategori karşılıklarını taşır.
- İletiler dizgi birleştirmesiyle değil tek bir kalıp ve yer tutucularla kurulur; eksik
  anahtar gizlenmez, eksik çeviri varsayılan dile düşer.
- Sayı, tarih, göreli zaman, liste ve sıralama platformun yerel ayar araçlarına bırakılır;
  Türkçede sıralama ve `i` harfinin dönüşümü yerel ayar verilmeden doğru sonuç vermez.
- Yön desteği belge, düzen ve metin düzeylerinde ayrı ele alınır; mantıksal özellikler
  düzeni, yalıtım ögesi karışık yönlü metni çözer.

## Kurs Kapanışı

Bu kurs, bir uygulamanın iç mimarisini dört soruyla kurdu.

**Kullanıcı nerede?** Yönlendirme konusu adresi uygulamanın durumunun bir parçası hâline
getirdi: iç içe düzenler ortak kabuğu paylaştırdı, rota parametreleri durumu adreste
taşıdı, rota koruma erişimi görünürlük düzeyinde yönetti, kod bölme her rotanın bedelini
kendine ödetti.

**Bilgi nerede duruyor?** Durum yönetimi konusu durumu türlerine ayırdı — yerel, paylaşılan,
sunucu ve adres durumu — ve her biri için farklı bir kap gösterdi. Sunucu durumunun ayrı
ele alınması, sonraki konunun kapısını açtı.

**Bilgi nasıl geliyor?** Veri erişimi konusu istek katmanını ve hata sözleşmesini kurdu,
sorgu tabanlı erişimin önbellek normalizasyonunu gösterdi, akış hâlinde gelen veriyi
kopmaya dayanıklı biçimde tüketti, görünümün durumlarını sayılı bir kümeye indirdi ve ağ
kararsızlığını kullanıcıya yansımadan soğurdu.

**Bilgi nasıl giriliyor ve kim giriyor?** Formlar ve kimlik konusu değerin nerede
tutulacağını, kuralların iki tarafta nasıl aynı kalacağını, hatanın nasıl algılanabilir
olacağını, kimlik kanıtının nerede saklanacağını, oturumun nasıl süreceğini ve arayüzün
dile nasıl uyarlanacağını kurdu.

Dördünün ortak yanı, hepsinin **tarayıcının içinde** geçmesi. Uygulama açıldıktan sonrasını
anlattık; açılmadan önce ne olduğunu hiç sormadık. Oysa aynı uygulama üç ayrı yerde
oluşturulabilir: kullanıcının tarayıcısında, isteği karşılayan sunucuda ya da daha istek
gelmeden derleme sırasında. Seçim, ilk ekranın ne kadar sürede geldiğini, arama motorunun
ne gördüğünü, sunucunun ne kadar iş yaptığını ve içeriğin ne kadar taze olabileceğini
belirler.

Bir sonraki kurs — **Oluşturma Stratejileri ve Altyapı** — bu seçimi ödünleşimleriyle
kurar: istemcide, sunucuda ve derleme zamanında oluşturmanın maliyetleri, statik çıktının
seçici tazelenmesi, etkileşimin parça parça kazanılması, paketleme ve varlık iyileştirme,
ve uygulamanın kullanıcıya ulaştığı dağıtım hattı.
