Sorunuzu sorun ve bu sayfaya ve seçtiğiniz AI sağlayıcısına referans vererek belgenin bir özetini alın
Sürüm Geçmişi
- "GitHub yıldız karşılaştırması ekle"v8.9.818.05.2026
- "Benchmark başlatıldı"v8.7.506.01.2026
Bu sayfanın içeriği bir yapay zeka kullanılarak çevrildi.
Orijinal içeriğin İngilizce son sürümünü görüntüleyinIf you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
TanStack Start i18n Kütüphaneleri - 2026 Benchmark Raporu
Bu sayfa, TanStack Start üzerindeki i18n çözümleri için hazırlanan bir kıyaslama (benchmark) raporudur.
İçindekiler
Etkileşimli Benchmark
Sonuçlar Referansı:
Tam kıyaslama verilerini görün
Benchmark deposunun tamamını buradan inceleyebilirsiniz.
Giriş
Uluslararasılaştırma çözümleri, bir React uygulamasındaki en ağır bağımlılıklardan biridir. TanStack Start'ta ana risk, gereksiz içerik gönderilmesidir: tek bir rotanın paketinde diğer sayfaların ve diğer yerel ayarların (locale) çevirilerinin bulunması.
Siteniz büyüdükçe, bu sorun istemciye gönderilen JavaScript miktarını hızla artırabilir ve navigasyonu yavaşlatabilir.
Pratikte, en az optimize edilmiş uygulamalar için uluslararasılaştırılmış bir sayfa, i18n bulunmayan sürüme göre birkaç kat daha ağır olabilir.
Diğer bir etki ise geliştirici deneyimidir (DX): içeriği nasıl tanımladığınız, tipler, ad alanı (namespace) organizasyonu, dinamik yükleme ve yerel ayar değiştiğinde verilen reaktif yanıt.
TL;DR
- Intlayer: TanStack Start için en iyi performansı ve en küçük paket boyutunu (v8.7.12) sağlar.
- react-i18next & use-intl: Geniş ekosistemlere sahip olgun alternatiflerdir, ancak optimize edilmeleri önemli ölçüde daha ağır ve karmaşıktır.
- Paraglide: Kağıt üzerinde yenilikçi bir tree-shaking fikridir ancak pratikte çalışmaz. TanStack Start'ta karmaşık DX ve reaktivite ek yükü oluşturur.
- Kaçının: Ciddi performans sorunları, AI kota sınırları ve satıcı kilidi (vendor lock-in) nedeniyle General Translation (GT) ve Lingo.dev.
Uygulamanızı Test Edin
i18n sızıntısı (leakage) sorunlarını hızlıca tespit etmek için buradan erişilebilen ücretsiz bir tarayıcı hazırladım.
Sorun
Çok dilli bir uygulamanın maliyetini sınırlamak için iki kaldıraç esastır:
- İçeriği sayfa / ad alanı bazında bölün, böylece ihtiyacınız olmadığında tüm sözlükleri yüklemezsiniz.
- Doğru yerel ayarı yalnızca gerektiğinde dinamik olarak yükleyin.
Bu yaklaşımların teknik sınırlarını anlamak:
Dinamik yükleme
Dinamik yükleme olmadan, çoğu çözüm mesajları ilk render'dan itibaren bellekte tutar ve bu da çok sayıda rota ve yerel ayara sahip uygulamalar için önemli bir ek yük oluşturur.
Dinamik yükleme ile bir ödün vermeyi kabul edersiniz: daha az başlangıç JS'i, ancak bazen dil değiştirirken ek bir istek.
İçerik bölme (Content splitting)
const t = useTranslation() + t('a.b.c') etrafında oluşturulan sözdizimleri çok kullanışlıdır ancak genellikle çalışma zamanında büyük JSON nesnelerinin tutulmasını teşvik eder. Kütüphane gerçek bir sayfa başına bölme stratejisi sunmadığı sürece bu model tree-shaking işlemini zorlaştırır.
Metodoloji
Bu benchmark için aşağıdaki kütüphaneleri karşılaştırdık:
Base App(i18n kütüphanesi yok)react-intlayer(v8.7.12)react-i18next(v17.0.2)use-intl(v4.9.1)@lingui/core(v5.3.0)@inlang/paraglide-js(v2.15.1)@tolgee/react(v7.0.0)react-intl(v10.1.1)wuchale(v0.22.11)gt-react(vlatest)lingo.dev(v0.133.9)
Framework, 10 sayfa ve 10 dilden oluşan çok dilli bir uygulamaya sahip TanStack Starttır.
Dört yükleme stratejisini karşılaştırdık:
Tüm veri içeriğini net bir şekilde görmek için tabloyu modalde açın
| Strateji | Ad alanı yok (global) | Ad alanı var (scoped) |
|---|---|---|
| Statik yükleme | Static: Başlangıçta her şey bellekte. | Scoped static: Ad alanına bölünmüş; her şey başlangıçta yüklü. |
| Dinamik yükleme | Dynamic: İstek üzerine dile göre yükleme. | Scoped dynamic: Ad alanına ve dile göre ayrıntılı yükleme. |
Strateji özeti
- Static: Basit; ilk yüklemeden sonra ağ gecikmesi yok. Dezavantajı: büyük paket boyutu.
- Dynamic: Başlangıç ağırlığını azaltır (lazy-loading). Çok sayıda yerel ayara sahip olduğunuzda idealdir.
- Scoped static: Karmaşık ek ağ istekleri olmadan kodu düzenli tutar (mantıksal ayrım).
- Scoped dynamic: Kod bölme (code-splitting) ve performans için en iyi yaklaşım. Yalnızca geçerli görünümün ve aktif dilin ihtiyaç duyduğu şeyi yükleyerek bellek kullanımını en aza indirir.
GitHub Yıldızları
GitHub yıldızları, bir projenin popülerliğinin, topluluk güveninin ve uzun vadeli alakasının güçlü bir göstergesidir. Teknik kalitenin doğrudan bir ölçüsü olmasa da, kaç geliştiricinin projeyi yararlı bulduğunu, ilerlemesini takip ettiğini ve benimseme olasılığını yansıtır. Bir projenin değerini tahmin etmek için yıldızlar, alternatifler arasındaki çekişi karşılaştırmaya yardımcı olur ve ekosistem büyümesi hakkında içgörüler sağlar.
Sonuçlar Detaylı
1 - Kaçınılması gereken çözümler
gt-react veya lingo.dev gibi bazı çözümler den kaçınılması gereken seçeneklerdir. Bu çözümler satıcı kısıtlamasını kod tabanınızı kirletmekle birleştirir. Daha da kötüsü: uygulamak için saatler harcanmasına rağmen TanStack Start üzerinde düzgün çalıştıklarını göremedim (Next.js'teki gt-nexte benzer şekilde).
Karşılaşılan sorunlar:
(General Translation) (gt-react@latest):
- Yaklaşık 110kb'lık bir uygulama için
gt-react440kb'tan fazla ek veri ekleyebilir (aynı benchmark'taki Next.js uygulamasında görülen miktar). - General Translation ile yapılan ilk derlemede
Quota Exceeded, please upgrade your planmesajı. - Çeviriler render edilmiyor; kütüphanede bir hata gibi görünen
Error: <T> used on the client-side outside of <GTProvider>hatası alıyorum. - gt-tanstack-start-react uygulanırken kütüphaneyle ilgili bir sorun ile de karşılaştım:
does not provide an export named 'printAST' - @formatjs/icu-messageformat-parserhatası uygulamayı bozdu. Bildirildikten sonra 24 saat içinde düzeltildi. - Bu kütüphaneler
initializeGT()fonksiyonu aracılığıyla bir antipaten (anti-pattern) kullanarak paketin temiz bir şekilde tree-shake edilmesini engeller.
(Lingo.dev) ([email protected]):
- AI kotası aşıldı (veya sunucu bağımlılığını engelliyor), bu da ödeme yapmadan derleme / yayınlamayı riskli hale getiriyor.
- Derleyici, çevrilmiş içeriğin neredeyse %40'ını kaçırıyordu. Çalışması için tüm
.mapyapılarını düz bileşen bloklarına yeniden yazmak zorunda kaldım. - CLI'ları hatalı ve yapılandırma dosyasını sebepsiz yere sıfırlıyordu.
- Derleme sırasında, yeni içerik eklendiğinde oluşturulan JSON'ları tamamen siliyordu. Sonuç olarak, birkaç anahtarın yüzlerce mevcut anahtarı sildiği bir durumla karşılaşabilirsiniz.
- TanStack Start üzerinde kütüphane ile reaktivite sorunları yaşadım: yerel ayar değiştiğinde çalışması için sağlayıcının (provider) zorla yeniden render edilmesini gerektirdi.
2 - Deneysel çözümler
(Wuchale) ([email protected]):
Wuchale'nin arkasındaki fikir ilginç ancak henüz uygulanabilir bir çözüm değil. Reaktivite sorunlarıyla karşılaştım ve TanStack Start üzerinde uygulamanın çalışması için sağlayıcının zorla yeniden render edilmesini gerektirdi. Dokümantasyon da oldukça belirsiz, bu da alışma sürecini zorlaştırıyor.
3 - Kabul edilebilir çözümler
(Paraglide) (@inlang/[email protected]):
Paraglide yenilikçi ve iyi düşünülmüş bir yaklaşım sunuyor. Buna rağmen, bu benchmark'ta şirketlerinin reklamını yaptığı tree-shaking benim Next.js uygulamamda veya TanStack Start için çalışmadı. İş akışı ve DX de diğer seçeneklerden daha karmaşık. Şahsen her push öncesinde JS dosyalarını yeniden oluşturmak zorunda kalmaktan hoşlanmıyorum, bu da PR'ler üzerinden geliştiriciler için sürekli merge çelişkisi riski yaratıyor.
paraglide üzerine not: Bu çözüm, içe aktarmalar (imports) için kod tabanınıza kod enjekte eder; sonuç olarak, benchmark raporundaki 'lib size' metriği neredeyse 0'dır. Kod üretimi (Code generation) iyi bir şeydir, porque kullanılan fonksiyon yalnızca gerekli mantığı (her yerde ön ek vs. ön ek yok, çerez vs. depolama vb.) içerecektir. Buna karşılık Intlayer, mantığa bağlı olarak paketleyicinin (bundler) içeriği tree-shake etmesini sağlamak için derleme sırasında ortam değişkeni enjeksiyonları yoluyla bu filtrelemeyi gerçekleştirir. Bu sayede paraglide ve intlayer, i18next veya next-intl'den 6 ila 10 kat daha hafif çözümler haline gelir.
(Tolgee) (@tolgee/[email protected]):
Tolgee daha önce bahsedilen sorunların çoğunu ele alıyor. Benzer yaklaşımlara sahip diğer araçlara göre başlamasının daha zor olduğunu gördüm. Tip güvenliği sağlamıyor, bu da eksik anahtarların derleme zamanında yakalanmasını çok zorlaştırıyor. Eksik anahtar algılama özelliği eklemek için Tolgee'nin API'larını kendi API'larımla sarmak zorunda kaldım.
TanStack Start üzerinde de reaktivite problemlerim oldu: yerel ayar değiştiğinde, sağlayıcıyı yeniden render etmeye zorlamam ve yerel ayar değişikliği olaylarına abone olmam gerekiyordu, böylece başka bir dildeki yükleme düzgün davrandı.
(use-intl) ([email protected]):
use-intl, React ekosistemindeki en popüler "intl" parçasıdır ( next-intl ile aynı aileden) ve genellikle AI asistanları tarafından önerilir; ancak bence performans odaklı bir ortamda bu yanlış bir yaklaşımdır. Başlamak oldukça basittir. Pratikte, sızıntıyı optimize etme ve sınırlama süreci oldukça karmaşıktır. Aynı şekilde, dinamik yükleme + ad alanı oluşturma + TypeScript tiplerini birleştirmek geliştirmeyi çok yavaşlatır.
TanStack Start'ta Next.js'e özgü tuzaklardan ( setRequestLocale, statik render) kaçınırsınız, ancak temel sorun aynıdır: sıkı disiplin olmazsa, paket hızla çok fazla mesaj taşır ve rota başına ad alanı bakımı zahmetli hale gelir.
(react-i18next) ([email protected]):
react-i18next muhtemelen en popüler seçenektir çünkü JavaScript uygulama i18n ihtiyaçlarını karşılayan ilklerden biridir. Ayrıca belirli sorunlar için geniş bir topluluk eklenti setine sahiptir.
Yine de, t('a.b.c') üzerine kurulu teknoloji yığınlarıyla aynı büyük dezavantajları paylaşır: optimizasyonlar mümkündür ancak çok zaman alıcıdır ve büyük projeler kötü uygulamalara (ad alanları + dinamik yükleme + tipler) düşme riski taşır.
Mesaj formatları da farklıdır: use-intl ICU MessageFormat kullanırken, i18next kendi formatını kullanır - bu da bunları karıştırdığınızda araçları veya geçişleri karmaşıklaştırır.
(Lingui) (@lingui/[email protected]):
Lingui sık sık övülür. Şahsen lingui extract / lingui compile iş akışını diğer yaklaşımlardan daha karmaşık buldum ve bu TanStack Start benchmark'ında net bir avantaj göremedim. Ayrıca AI'ları şaşırtan tutarsız sözdizimleri fark ettim (örneğin t(), t'', i18n.t(), <Trans>).
(react-intl) ([email protected]):
react-intl, Format.js ekibinin performans odaklı bir uygulamasıdır. DX "verbose" kalır: const intl = useIntl() + intl.formatMessage({ id: "xx.xx" }) karmaşıklık, ek JavaScript yükü ekler ve global i18n örneğini React ağacındaki birçok düğüme bağlar.
4 - Öneriler
Bu TanStack Start benchmark'ının next-translate (Next.js eklentisi + getStaticProps) için doğrudan bir karşılığı yoktur. Gerçekten olgun bir ekosisteme sahip bir t() API'si isteyen ekipler için react-i18next ve use-intl "makul" seçenekler olmaya devam ediyor, ancak sızıntıyı önlemek için optimizasyon yapmaya çok zaman ayırmaya hazırlıklı olun.
(Intlayer) ([email protected]):
Nesnellik adına kendi çözümüm olan react-intlayer hakkında kişisel olarak yorum yapmayacağım.
Kişisel Not
Bu not kişiseldir ve benchmark sonuçlarını etkilemez. Yine de i18n dünyasında, çevrilmiş içerik için genellikle const t = useTranslation('xx') + <>{t('xx.xx')}</> gibi bir desen etrafında fikir birliği görülür.
React uygulamalarında, bir React düğümü (ReactNode) olarak bir fonksiyon enjekte etmek bence bir antipatendir. Ayrıca, kaçınılabilir bir karmaşıklık ve (zar zor fark edilse bile) JavaScript yürütme yükü ekler.