Yazar:
    Oluşturma:2026-09-16Son güncelleme:2026-09-16

    Doğru Solid i18n kütüphanesi nasıl seçilir

    Solid'in reaktivite modeli, bir i18n kütüphanesinin yapması gerekenleri değiştirir. Bileşenler yalnızca bir kez çalışır; bu nedenle setup aşamasında bir const içinde saklanan bir çeviri donmuş bir string (frozen string) haline gelir. Size accessor yerine string veren bir kütüphane, birinin bu hatayı yaptığı üç bileşen haricinde her yerde dil değiştiren bir sayfa üretir. Solid için bir kütüphane seçmek kısmen API ile, kısmen de hangisinin bu hatayı yapmayı zorlaştırdığıyla ilgilidir.

    Bu rehber, önce yanıtlanması gereken soruları listeler, ardından bunları Vite + Solid ve SolidStart için @solid-primitives/i18n, solid-i18next, Paraglide, @lingui/solid ve Intlayer ile eşleştirir.

    Solid i18n kütüphane ekosistemi

    İçindekiler

    Kütüphaneleri karşılaştırmadan önce yanıtlanması gereken altı soru

    1. Vite SPA mı yoksa SolidStart mı? Bir SPA'da locale yalnızca bir signal içinde yaşayabilir ve başka hiçbir şeye ihtiyaç duymaz. SolidStart'ta ise locale'in sunucuda URL'den çözümlenmesi gerekir ve bir crawler'ın JavaScript olmadan görmesi gereken her şey (<html lang>, hreflang) entry-server.tsx dosyasında yer almalıdır.
    2. Locale değişikliğinin ne kadar reaktif olması gerekiyor? Dil değişiminde tam sayfa yenilenmesi bazı uygulamalar için kabul edilebilirdir. Eğer değilse, kütüphanenin değerleri signal veya accessor olmalı ve bunların okunması kopyalanmak yerine track edilmelidir.
    3. Çevirileri kim yazıyor? Geliştiriciler, bir TMS, ICU string'leri teslim eden bir ajans veya bir AI pipeline'ı. solid-i18next i18next'in formatını kullanır. @solid-primitives/i18n sözlük nesneniz neyse odur. Tercihinizi kaynağınıza göre belirleyin.
    4. Kaç locale ve sayfa var? İki locale ve beş sayfa her şeyi tek seferde sunabilir. On locale ve kırk route bunu sunamaz; bu durumda lazy catalog'lar ve scoping ana maliyet haline gelir.
    5. Key'lerde type güvenliğine ihtiyacınız var mı? @solid-primitives/i18n bunları kaynak sözlükten infer eder. solid-i18next manuel tanımlama gerektirir. Compile-time kütüphaneleri ise bunları otomatik olarak üretir (generate eder).
    6. Ne kadar özellik kapsamına ihtiyacınız var? Cookie yönetimi, locale önekli (locale-prefixed) routing, redirect'ler, formatter'lar. En hafif seçenekte bunların hiçbiri yoktur ve yetersiz kalana kadar bu durum gayet iyidir.

    Yanıtları bir yere not edin. Aşağıdaki her şey bunlara atıfta bulunacaktır.

    Tek bir resimde genel görünüm

    Solid buradaki en genç ekosistemdir ve üç dalgaya yayılmış en az seçeneğe sahiptir.

    JavaScript i18n kütüphanelerinin tarihi

    Solid için sarmalanmış (wrapped) i18next. Namespace'ler, backend'ler, detector'lar ve on yıllık eklenti birikimi. Grubun en ağırı ve React'tekiyle aynı t("a.b") maliyetlerine sahip.

    Sizin kontrolünüzde olan düz (flat) bir sözlük, accessor'lar döndüren bir translator(), kaynak nesneden infer edilen type'lar. Oldukça küçük, scoping yok, routing yok, formatter yok. Topluluğun varsayılan tercihi.

    Paraglide mesaj başına bir fonksiyon üretir. Intlayer, içeriği .content.ts dosyalarında bileşen başına tanımlar ve signal destekli node'lar döndürür. Lingui'nin Solid desteği 2026'da geldi ve makro tabanlı ayıklama (extraction) özelliğini beraberinde getirir.

    JavaScript i18n tarihi her dalgayı ayrıntılı olarak ele alır.

    En önemli karar: İçerik nerede yaşar ve ne zaman yüklenir

    Kurulumlar arasındaki bundle farkının çoğunu iki yapısal tercih açıklar:

    • Merkezi veya kapsamlandırılmış (scoped) içerik. Uygulama için tek bir sözlük ya da bileşen başına bir tanımlama.
    • Statik veya dinamik import. Başlangıçta her şeyi yükleme ya da aktif locale'i (ve ideal olarak aktif route'u) isteğe bağlı (on demand) getirme.

    Grafik, sayfa başına yaklaşık 30 KB metin içeren, 1 ila 10 locale'e çevrilmiş 1 ila 10 sayfalık teorik bir uygulama için payload tahminini göstermektedir.

    Mimariye göre teorik içerik sızıntısı

    @solid-primitives/i18n her iki eksende de hiçbir şey yapmaz: locale başına bir sözlüğü createResource ile yüklersiniz; bu size dinamik yükleme sağlar, gerisi size kalır. solid-i18next namespace'lere ve lazy backend'lere sahiptir, ancak eşlemeyi zorunlu kılan hiçbir şey yoktur; bu nedenle common import eden paylaşılan bir bileşen, onu her route'un bir bağımlılığı haline getirir. Paraglide, sayfa eksenini tree-shaking ile çözer; ancak bu durum Solid benchmark uygulamasında etkili olmadı. Intlayer ise bunu bileşen başına tanımlamalarla sağlar.

    1. soruya yanıtınız "çok sayıda sayfa" ise, bu bölüme herhangi bir API tercihinden daha fazla önem verin. Bileşen başına ve merkezi i18n karşılaştırması yazısı, aynı trade-off'un bakım boyutunu ele almaktadır.

    Adaylar

    Kütüphane boyutları Solid benchmark çalışmasından alınmıştır: 10 sayfalık, 10 locale'e sahip bir uygulamada; bundling, tree-shaking ve minification sonrasında boş bir bileşendeki provider artı accessor. İçerik ayrıca ölçülür.

    Kütüphaneİçerik modeliLocale değişiminde reaktiviteKey'lerde type desteğiScoping ve lazy loadingKütüphane boyutu
    @solid-primitives/i18nSize ait düz sözlükSignal, translator tarafından döndürülen accessor'larKaynak sözlükten infer edilirYerleşik olarak yokÇok küçük
    solid-i18nexti18next katalogları ve namespace'leriStore, provider üzerinden re-renderManuel tanımlamaNamespace'ler, lazy backend'ler~14.9 kB
    Paraglideinlang projesi, üretilen fonksiyonlarCookie veya storage'dan çağrı başına okumaOtomatik üretilir (generated)Tree-shaking (benchmark'ta etkisiz)Sıfıra yakın
    @lingui/solidKod içinde kaynak metin, derlenmiş kataloglarSignal tabanlıDerleyiciden sağlanırKatalog başınaKüçük
    IntlayerBileşen başına bir .content.tsSignal destekli node'lar, bileşen re-run'ı yokÜretilir (generated), varsayılan olarak açıkEvet, bileşen başınaReferans (Baseline)
    Rakamlar, benchmark sırasındaki sürümlerin anlık görüntüsüdür. @lingui/solid benchmark'ta yer almamıştır. Yalnızca boyuta göre karar vermeden önce kendi uygulamanızda test edin.

    Paraglide'ın sıfıra yakın kütüphane boyutu yapısı gereğidir: runtime doğrudan projenize üretilir (generate edilir). Intlayer vite-intlayer gerektirir, bu yüzden bir build adımı olmadan çalışamaz.

    Yanıtlarınızı bir kütüphaneyle eşleştirin

    @solid-primitives/i18n. Düz bir sözlük, accessor'lar döndüren bir translator(), hiçbir ek yapılandırma olmadan infer edilen type'lar. Küçük bir uygulama için doğru tercihtir ve kaynak kodunu okumak on dakika sürer. Kendiniz yazmanız gerekenler: locale kalıcılığı (persistence), routing, formatter'lar ve route başına kod bölme (splitting). Bu liste uzadıkça, bu durum geçiş yapma vaktinin geldiğinin bir işaretidir.

    solid-i18next, katalogları, namespace'leri, backend'leri ve detector'ları olduğu gibi yeniden kullanmanızı sağlar. En ağır seçenektir ve react-i18next ile aynı maliyetleri taşır: manuel type tanımlamaları, mümkün olan ancak zaman alan optimizasyonlar ve string döndüren bir t(); bu nedenle donmuş çeviri hatasını yazmak oldukça kolaydır. Okumaları JSX veya memo içinde sarmalayın ve setup sırasında asla saklamayın.

    Her iki tarafın da uyuşması için locale'in sunucuda URL'den gelmesi gerekir; bunu istemcide tespit etmek çok geçtir. @solid-primitives/i18n ve solid-i18next, [[locale]] route'unu, matchFilters yapısını, redirect'i ve entry-server.tsx etiketlerini size bırakır. Paraglide, routing'i yöneten bir Vite eklentisine sahiptir. Intlayer, middleware ve route yardımcılarını hazır olarak sunar. Hangisini seçerseniz seçin, <html lang> ve hreflang etiketlerini entry-server.tsx içine yerleştirin; SolidStart v2'de @solidjs/meta istemcide hydration sonrasında uygulanır. Solid i18n yazısı bu kurulumu adım adım açıklar.

    Değerleri signal veya accessor olan ve okumaları track edilen bir kütüphane seçin. @solid-primitives/i18n accessor'ları ve Intlayer node'larının her ikisi de, bileşeni yeniden çalıştırmadan yalnızca kendilerini okuyan DOM node'larını günceller. solid-i18next, provider üzerinden re-render eder. Paraglide, locale'i bir signal yerine her mesaj çağrısında cookie veya storage'dan okur; bu yöntem çalışır ancak node başına gerekenden daha fazla işlem yapar.

    Build zamanında derlenen scoped içerik. Intlayer yalnızca bir route'un render ettiği içeriği sunar. Paraglide'ın buraya tree-shaking ile ulaşması beklenir; benchmark testinde çalışmadığından kendi kurulumunuzda bunu doğrulayın. solid-i18next ile namespace ve lazy-loading stratejisini ilk günden planlayın ve code review süreçlerinde bunu denetleyin.

    @solid-primitives/i18n, çoğu React kütüphanesinin sunduğundan daha fazlasını sunarak size hiçbir ek çaba gerektirmeden infer edilmiş type'lar sağlar. Lazy loading ve route başına bölme sonrasında da geçerliliğini koruyan üretilmiş (generated) type'lar için Paraglide, @lingui/solid ve Intlayer'ın tümü bunları içerikten üretir. Eksik çevirileri tespit etme yazısı, her birinin build zamanında neleri yakaladığını karşılaştırır.

    Bu durumda merkezi bir sözlüğü haklı çıkaracak hiçbir kullanıcı kalmaz. Colocated içerik ve eksik locale'leri dolduran bir CLI en kısa yoldur. Intlayer'ın fill komutu kendi API key'inizle (OpenAI, Anthropic, Mistral, Gemini) çalışır ve yalnızca değişen kısımları yeniden çevirir.

    Her kütüphanenin yetersiz kaldığı noktalar

    • @solid-primitives/i18n: Kendi oluşturduklarınızın ötesinde lazy loading veya scoping yoktur, routing, cookie yönetimi ve formatter bulunmaz. Küçük uygulamalar için mükemmeldir, profesyonel projeler için hızla yetersiz kalır.
    • solid-i18next: Grubun en ağırı, manuel type tanımları, kendine has çoğul (plural) formatı ve t() fonksiyonunun string döndürmesi nedeniyle setup sırasında saklanan çevirilerin donması riski.
    • Paraglide: Oluşturulan dosyalar repoya commit edilir ve her push öncesinde yeniden üretilir, Solid benchmark testinde tree-shaking etkili olmadı ve locale bir signal yerine çağrı başına storage'dan okunur.
    • @lingui/solid: 2026'da yeni çıktı, bu nedenle henüz yeterli üretim (production) geri bildirimi yok. Lingui'nin extract / compile build adımını ve birbiriyle örtüşen çeşitli sözdizimlerini miras alır.
    • Intlayer: Zorunlu build eklentisi, daha küçük ekosistem, kısmi ICU desteği ve tasarım gereği içeriklerin kod tabanına yayılmış olması; bu nedenle bir çevirmen için tek bir JSON export etmek ek araçlar gerektirir.

    Her seçeneğin kodda görünümü

    Her adayla yazılmış aynı bileşen: başlık ve çoğul içeren bir sepet özeti. Çevirinin nerede okunduğuna dikkat edin: JSX içinde track edilir, setup gövdesinde ise donmuş bir string haline gelir.

    src/i18n/index.ts
    import * as i18n from "@solid-primitives/i18n";
    
    export const en = {
      cart: { title: "Your cart", items: "{{ count }} items" },
    };
    
    export const dictionary = () => i18n.flatten(en);
    export const t = i18n.translator(dictionary, i18n.resolveTemplate);
    
    src/components/CartSummary.tsx
    import type { Component } from "solid-js";
    import { t } from "../i18n";
    
    export const CartSummary: Component<{ count: number }> = (props) => (
      <section>
        <h2>{t("cart.title")}</h2>
        <p>{t("cart.items", { count: props.count })}</p>
      </section>
    );
    

    Key'ler kod üretimi olmadan doğrudan İngilizce nesneden type'landırılır. Çoğul kuralı, lazy loading ve routing yoktur; her birini eklemek size kalmıştır.

    public/locales/en/cart.json
    {
      "title": "Your cart",
      "items_one": "{{count}} item",
      "items_other": "{{count}} items"
    }
    
    src/components/CartSummary.tsx
    import { useTransContext } from "@mbarzda/solid-i18next";
    import type { Component } from "solid-js";
    
    export const CartSummary: Component<{ count: number }> = (props) => {
      const [t] = useTransContext();
    
      return (
        <section>
          <h2>{t("cart:title")}</h2>
          <p>{t("cart:items", { count: props.count })}</p>
        </section>
      );
    };
    

    i18next katalogları, namespace'leri ve eklentileri olduğu gibi kullanılır. t bir string döndürür, bu yüzden setup aşamasında const title = t("cart:title") kullanımı onu dondurur; çağrıyı JSX içinde tutun.

    messages/en.json
    {
      "cart_title": "Your cart",
      "cart_items": "{count} items"
    }
    
    src/components/CartSummary.tsx
    import type { Component } from "solid-js";
    import { m } from "../paraglide/messages.js";
    
    export const CartSummary: Component<{ count: number }> = (props) => (
      <section>
        <h2>{m.cart_title()}</h2>
        <p>{m.cart_items({ count: props.count })}</p>
      </section>
    );
    

    Her mesaj üretilmiş (generated), type güvenli bir fonksiyondur. Locale, bir signal yerine her çağrıda cookie veya storage'dan okunur; bu nedenle dil değişimindeki reaktiviteyi kurmak size aittir.

    src/components/cartSummary.content.ts
    import { type Dictionary, plural, t } from "intlayer";
    
    const cartSummaryContent = {
      key: "cart-summary",
      content: {
        title: t({
          tr: "Sepetiniz",
          en: "Your cart",
          fr: "Votre panier",
          es: "Tu carrito",
        }),
        items: plural({
          one: t({
            tr: "{{count}} ürün",
            en: "{{count}} item",
            fr: "{{count}} article",
          }),
          other: t({
            tr: "{{count}} ürün",
            en: "{{count}} items",
            fr: "{{count}} articles",
          }),
        }),
      },
    } satisfies Dictionary;
    
    export default cartSummaryContent;
    
    src/components/CartSummary.tsx
    import { useIntlayer } from "solid-intlayer";
    import type { Component } from "solid-js";
    
    export const CartSummary: Component<{ count: number }> = (props) => {
      const content = useIntlayer("cart-summary");
    
      return (
        <section>
          <h2>{content.title}</h2>
          <p>{content.items(props.count)}</p>
        </section>
      );
    };
    

    Tüm locale'ler bileşenin hemen yanında tek bir dosyada yer alır. useIntlayer signal destekli node'lar döndürür, böylece bir locale değişikliği yalnızca onları okuyan DOM node'larını günceller. JSX içindeki {content.title} track edilir; setup gövdesindeki content.title.value ise track edilmez.

    Mevcut bir i18next kod tabanında, i18next uyumluluk adaptörü, paket alias'ını bundler seviyesinde tanımlar; böylece Intlayer içeriği sunarken kataloglar ve t() çalışmaya devam eder. Geri kalan konuları geçiş rehberi ele alır.

    Karar vermeden önce

    Bir özellik tablosu size bir kütüphanenin bugün ne yaptığını gösterir. Bu maddeler ise onunla yaşamanın nasıl bir deneyim olacağını anlatır.

    Repository aktivitesini kontrol edin.

    Commit'ler, issue yanıtlama süreleri ve son minör sürümün bu yıl çıkıp çıkmadığı. Bakımı yapılmayan iyi bir mimari, ertelenmiş bir migrasyondur.

    npm indirme sayılarına göre seçim yapmayın.

    En çok indirilen kütüphane ilk çıkan kütüphanedir, 2026 yılındaki bir Solid projesine en uygun olanı değil. İndirmeler uygunluğu değil, tarihi ölçer.

    JavaScript i18n kütüphaneleri tier listesi

    Geliştiriciyi kimin fonladığını ve ne sattıklarını sorgulayın.

    solid-i18next'in arkasındaki i18next, Locize tarafından desteklenmektedir. next-intl, vue-i18n, svelte-i18n ve Lingui Crowdin tarafından desteklenir. Tolgee, Paraglide (inlang) ve Intlayer'ın her biri kendi platformunu yürütür. Geliri barındırılan çeviri hizmetleri olan bir şirketin, araç zinciriniz içinde çeviriyi ücretsiz hale getirmek için pek bir nedeni yoktur. Intlayer, grupta kendi API key'inizle CLI üzerinden yapay zeka çevirisi sunan ve self-host edebileceğiniz bir CMS sağlayan tek seçenektir.

    Yapay zeka (AI) ajanlarına hazır mı?

    Ajanlar i18n konusunda hâlâ zorlanmaktadır: locale'leri unuturlar, key uydururlar ve mesaj sözdizimlerini karıştırırlar. Kütüphane, ajanın içeriği listeleyebilmesi, doldurabilmesi ve test edebilmesi için Agent Skills veya bir MCP sunucusu sunuyor mu? İçerik yüklemesi varsayılan olarak optimize edilmiş mi, yoksa birinin her çeyrekte namespace'leri ve lazy import'ları gözden geçirmesi mi gerekiyor?

    Kutudan çıktığı gibi type güvenliği.

    "Ekstra yapılandırmalarla type eklenebilir" değil, "hatalı bir key yeni bir kurulumda tscyi patlatır". Var olmayan bir key girildiğinde ve bir çevirisi eksik olan bir locale durumunda ne olduğunu kontrol edin.

    Kullanılmayan içeriğin tespiti.

    Kataloglar yalnızca büyür. Intlayer'ın build işlemi kullanılmayan alanları temizler ve bunları günlüğe kaydeder (build.purge). Paraglide mimarisi gereği buna ulaşır, çünkü çağrılmayan bir mesaj fonksiyonu tree-shake edilir. Diğer her seçenek temizlik işini size bırakır.

    Geliştirici deneyimi (DX).

    İlk çevrilmiş string'e kadar geçen kurulum süresi, üzerine gelindiğinde (hover) çeviriyi gösteren ve bildirime atlayan bir LSP veya VS Code eklentisi, doldurma, test ve push işlemleri için bir CLI ve yazılımcı olmayan kişilerin bir pull request açmadan içeriği düzenlemesi için bir yol (görsel editör veya CMS).

    Sıkça Sorulan Sorular

    Küçük bir uygulama için evet ve mevcut en hafif seçenektir. Route başına lazy kataloglara, SolidStart'ta locale routing'e, cookie kalıcılığına veya formatter'lara ihtiyaç duyduğunuzda yetersiz kalır çünkü bunların hepsini kendiniz oluşturmanız gerekir.

    Çünkü Solid bileşenleri yalnızca bir kez çalışır. Setup sırasında bir const içine okunan bir çeviri düz bir string'dir, reaktif bir abonelik (subscription) değildir. Çeviriyi JSX, effect veya memo içinde okuyun ya da hatalı kullanımı zorlaştırmak için değerleri accessor olan bir kütüphane tercih edin.

    Yalnızca bundle boyutu, otomatik üretilen type'lar veya build anında eksik anahtar kontrolleri gerçek gereksinimleriniz arasındaysa. Derleyici ve deklaratif i18n karşılaştırması yazısı, derleyicilerin size ne kazandırdığını ve nerelerde yanılabileceğini açıklamaktadır.

    Dolaylı olarak etkiler. Arama motoru botları (crawler'lar) routing, hreflang, <html lang> ve metnin sunucu tarafından render edilen HTML içinde yer alıp almadığına bakar; bu durum SolidStart'ta entry-server.tsx anlamına gelir. hreflang rehberi yazısına göz atın.

    Daha fazlası

    Yorumlar

    Henüz yorum yok. Düşüncelerinizi paylaşan ilk kişi olun.

    İlgili Gönderiler

    Son Gönderiler