Mühendislik//12 dk okuma

Büyük Çeviri Dosyalarını Bölme: Namespace Bazlı Yükleme ile Daha Hızlı Uygulamalar

Ali Osman Delismen
Paylaş

Çeviri dosyalarınız sayfa yükleme sürelerinizi sessizce öldürüyor. 500+ anahtarlı tipik bir uluslararasılaştırılmış uygulama, dil başına 400-800KB çeviri paketi üretir. Bunu 15 dil ile çarpın ve 6-12MB çeviri verisi sunuyorsunuz — bunun çoğunu kullanıcılar asla görmez.

Bu rehber, bunun neden olduğunu, namespace bazlı bölmenin bunu nasıl çözdüğünü ve çeviri yüklerini %90-97 azaltan pratik implementasyon kalıplarını kapsar.

Monolitik Çeviri Dosyalarının Gizli Maliyeti

Çoğu i18n kurulumu basit başlar: locale başına tek bir translations.json dosyası. 50 anahtarda gayet iyi çalışır. Ama production uygulamalar hızla büyür:

ÖlçekAnahtarDosya Boyutu (gzip)Etki
Küçük uygulama50~2 KBİhmal edilebilir
Orta uygulama500~18 KB3G'de fark edilir
Büyük uygulama2.000~70 KBÖnemli
Kurumsal5.000+~200 KBKritik darboğaz

Sorun birden fazla dille katlanır. 15 dilde 500 anahtarlı bir uygulama, kullanıcı herhangi bir içerik görmeden önce CDN'nin 270KB çeviri verisi sunması demektir — ve yalnızca mevcut sayfa için çevirilere ihtiyaç duyarlar (tipik olarak 20-50 anahtar, ~2KB).

Gerçek dünya örneği: Better i18n'deki kendi landing sayfamız 59 namespace'te 699 anahtara ulaştı. İngilizce translations.json 478KB idi. Hintçe çeviri 841KB idi. Her ziyaretçi, yalnızca fiyatlandırma sayfasını ziyaret etse bile (14 anahtar, ~2KB gerekli) tüm dosyayı indiriyordu.

i18n Namespace'leri Nedir?

Namespace'ler, çevirilerinizdeki mantıksal gruplardır — genellikle sayfa, özellik veya alana göre düzenlenir:

{
  "hero": {
    "title": "Çevirileri daha hızlı gönderin",
    "subtitle": "Modern uygulamalar için AI destekli lokalizasyon"
  },
  "pricing": {
    "title": "Basit, şeffaf fiyatlandırma",
    "monthly": "Aylık",
    "yearly": "Yıllık"
  },
  "footer": {
    "copyright": "© 2026 Acme Inc.",
    "privacy": "Gizlilik Politikası"
  }
}

i18next, react-intl ve Better i18n gibi kütüphaneler namespace'leri destekler. Tipik kullanım useTranslations("pricing") şeklindedir — SDK'ya hangi namespace'e ihtiyacınız olduğunu zaten söylüyorsunuz. SDK sadece bu bilgiyi yükleme optimizasyonu için kullanmıyor.

Çeviri Dosyalarını Bölmek İçin Üç Strateji

Strateji 1: Namespace Bazlı CDN Dosyaları

Tek monolitik dosya yerine, her namespace'i ayrı dosya olarak yayınlayın:

Önce:
  /en/translations.json     → 478 KB (tüm 59 namespace)

Sonra:
  /en/translations.json     → 478 KB (geriye uyumlu)
  /en/hero.json             → 1.2 KB
  /en/pricing.json          → 2.1 KB
  /en/footer.json           → 0.8 KB
  ...59 bireysel dosya

Bir sayfa hero + pricing + footer gerektirdiğinde:

  • Önce: 1 istek × 478 KB = 478 KB
  • Sonra: 3 istek × ~1.4 KB ort = 4.1 KB (%99 azalma)

Takas, daha fazla HTTP isteğidir. Ancak HTTP/2 multiplexing ile 3-6 küçük paralel istek, 1 büyük istekten daha hızlı tamamlanır. Ve her namespace dosyası bağımsız olarak önbelleğe alınır — pricing güncellemek hero'yu geçersiz kılmaz.

Strateji 2: Namespace Sorgu Parametresi

Tek dosyalı CDN yapısını koruyun ama sunucu tarafında filtreleme ekleyin:

GET /en/translations.json?ns=hero,pricing,footer
← Yalnızca istenen namespace'leri döndürür (~4 KB)

Avantajlar:

  • Tek HTTP isteği (waterfall yok)
  • R2/S3 depolama ek yükü yok (dosyalar çoğaltılmaz)
  • Geriye uyumlu (?ns parametresi yoksa = tam dosya)

Dezavantajlar:

  • CDN worker mantığı gerektirir (statik dosya sunamaz)
  • Cache key karmaşıklığı (her namespace kombinasyonu farklı)
  • Edge'de önbelleğe almak zor (sorgu parametreleri cache hit oranını düşürür)

Strateji 3: Build-Time Code Splitting

Next.js ve Vite gibi framework'ler çevirileri build zamanında bölebilir:

// dynamic import ile next-i18next
const i18nConfig = {
  ns: ['common', 'pricing'],
  resourceLoader: (language, namespace) =>
    import(`./locales/${language}/${namespace}.json`),
};

Bu, yalnızca her sayfanın import ettiği çevirileri paketler. Webpack/Vite namespace başına ayrı chunk'lar oluşturur.

Avantajlar:

  • Sıfır runtime ek yükü (build'de çözülür)
  • SSR/SSG ile çalışır (çeviriler server bundle'ına dahil)
  • Tree-shaking kullanılmayan anahtarları elimine eder

Dezavantajlar:

  • Yalnızca dosya tabanlı çevirilerle çalışır (CDN dağıtımı değil)
  • Çevirileri güncellemek için rebuild gerektirir
  • OTA (over-the-air) çeviri güncellemelerine yardımcı olmaz

Optimal Mimari: CDN + Akıllı Yükleme

En iyi yaklaşım, CDN düzeyinde namespace dosyaları ile SDK düzeyinde akıllı yüklemeyi birleştirir:

CDN yayınlar:
├── /en/translations.json     ← tam paket (geriye uyumlu)
├── /en/hero.json             ← namespace bazlı
├── /en/pricing.json
├── /en/footer.json
└── /manifest.json            ← namespace listesi + URL'ler içerir

SDK davranışı:
1. manifest.json'ı getir (önbellekli, küçük)
2. Mevcut sayfanın hangi namespace'lere ihtiyacı olduğunu algıla
3. Yalnızca bu namespace dosyalarını toplu getir
4. Her namespace'i bağımsız olarak önbelleğe al
5. Navigasyonda eksik namespace'leri artımlı getir

Bu size şunları sağlar:

  • Minimum başlangıç yükü — yalnızca mevcut sayfanın ihtiyaç duyduğu
  • Hızlı navigasyon — paylaşılan namespace'ler (header, footer) zaten önbellekte
  • Bağımsız cache invalidation — bir namespace'i güncellemek diğerlerini bozmaz
  • Sıfır geliştirici ek yüküuseTranslations("pricing") aynı şekilde çalışır
  • Geriye uyumluluktranslations.json hala tam paketi sunar

Performans Karşılaştırmaları

Kendi landing sayfamızda namespace bölmenin etkisini ölçtük (699 anahtar, 59 namespace, 15 dil):

MetrikÖnce (monolitik)Sonra (namespace bölme)İyileşme
Çeviri yükü478 KB12 KB (sayfa ort.)%97.5 daha küçük
Time to First Byte180ms45ms%75 daha hızlı
Toplam CDN bant genişliği/ay48 GB2.1 GB%95.6 daha az
Cache hit oranı%62%94+32 puan

Cache hit oranı iyileşmesi granüler önbelleğe almadan gelir — pricing metnini güncellediğinizde yalnızca /en/pricing.json geçersiz kılınır. Diğer 58 namespace dosyası edge'de önbellekte kalır.

Ne Zaman Bölmemeli?

Namespace bölme her zaman doğru seçim değildir:

  • Küçük uygulamalar (< 100 anahtar): Gzip'li çeviriler ~4KB'dir. Bölme, anlamlı fayda olmadan karmaşıklık ekler.
  • SSG ile statik siteler: Çeviriler build zamanında paketlenip statik HTML olarak sunuluyorsa, optimize edilecek runtime yükü yoktur.
  • Preloading'li tek sayfa uygulamalar: SPA'nız splash ekranı sırasında tüm çevirileri preload ediyorsa, bölme algılanan performansı iyileştirmez.

Pratik kural: Çeviri dosyanız 50KB gzip'li (kabaca 1.000+ anahtar) aşıyorsa, namespace bölme yükleme sürelerini anlamlı şekilde iyileştirecektir.

Sonuç

Büyük çeviri dosyaları çözülebilir bir performans problemidir. Mimari basittir:

  1. Namespace bazlı dosyalar yayınlayın — tam çeviri paketinizin yanında
  2. SDK'nın yalnızca gerekeni yüklemesine izin verinuseTranslations() çağrılarına göre
  3. Bağımsız önbelleğe alın — bir namespace güncellemesi diğerlerini geçersiz kılmasın

Bu yaklaşım, namespace'leri destekleyen herhangi bir i18n kütüphanesiyle çalışır (i18next, react-intl, Better i18n, LinguiJS). CDN düzeyindeki değişiklik evrenseldir — uygulama kodunuz aynı kalır.

500+ anahtarla 15+ dile hizmet veren uygulamalar için, bu tek değişiklik çeviri yüklerini %90-97 azaltabilir ve CDN bant genişliğini %95 kesebilir. Bu, daha iyi Core Web Vitals, daha hızlı time-to-interactive ve dünya genelinde daha mutlu kullanıcılar demektir.

Comments

Loading comments...