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

    next-intl ve Intlayer Karşılaştırması | React & Next.js Uluslararasılaşma (i18n) Testi

    next-intl, günümüzde Next.js App Router için varsayılan tercihtir: yönlendirme ile sıkı entegrasyon, eksiksiz ICU MessageFormat desteği ve klasik i18n sistemlerini kullanmış olan herkes için tanıdık bir geliştirici deneyimi sunar.

    Intlayer ise soruna temelden farklı yaklaşır: merkezi sözlükler yoktur, ad alanlarını (namespaces) rotalarla manuel olarak eşleştirme zahmeti bulunmaz. İçerik her bileşenin hemen yanında bildirilir ve derleme zamanı derleyicisi her sayfanın tam olarak neye ihtiyacı varsa yalnızca onu paketler.

    Bu makale, her iki kütüphaneyi aynı uygulamayı derleyen ve tarayıcının gerçekte ne indirdiğini ve çalıştırdığını kaydeden açık kaynaklı bir test paketi olan Benchmark Bloom verilerine dayanarak karşılaştırmaktadır.

    Özetle (tl;dr): next-intl, yalnızca çalışma zamanı için sayfa başına en az +12.6 KB gzip ekler ve standart kurulumlarında (static ve dynamic) diğer sayfaların dizgilerinin yaklaşık %90'ını sızdırır. Bu sızıntıyı gidermek, katalogları ad alanlarına bölmeyi ve sayfa başına manuel olarak seçmeyi gerektirir. Buna karşılık, Intlayer derleyicisi herhangi bir manuel yapılandırma olmadan %0 sızıntı, 3 kat daha küçük bileşenler ve temel uygulamanın üzerine yalnızca +0.3 KB ek yük sağlar.

    Kısaca

    • next-intl - Next.js topluluk standardı. Dil başına merkezi JSON sözlükleri, tam ICU MessageFormat desteği ve Next.js istek işleme ile yönlendirme mekanizmasına derin entegrasyon.
    • Intlayer - Bileşen odaklı içerik modeli. .content.ts dosyaları doğrudan bileşenlerin yanında bulunur, derleme zamanı derleyicisi bunları bileşen ve dil başına tree-shake ve tembel yükleme yapar, katı TypeScript tiplerini otomatik üretir.
    KütüphaneGitHub YıldızlarıToplam CommitSon Commitİlk SürümNPM SürümüNPM İndirmeleri
    aymericzip/intlayerGitHub Repo starsGitHub commit activityLast CommitNisan 2024npmnpm downloads
    amannn/next-intlGitHub Repo starsGitHub commit activityLast CommitMart 2021npmnpm downloads
    Rozetler otomatik olarak güncellenir.

    Özellik karşılaştırması

    ÖzellikIntlayer (react-intlayer / next-intlayer)next-intl (next-intl / use-intl)
    Bileşenlerin yanında çeviriler✅ Evet, .content.ts her bileşenin hemen yanında bulunurmessages/ dizininde merkezi JSON sözlükleri
    TypeScript entegrasyonu✅ İçerikten otomatik üretilen katı tipler⚠️ Manuel global.d.ts kurulumuyla desteklenir
    Eksik çeviri tespiti✅ TypeScript hatası + derleme zamanı hatası/uyarısı⚠️ Çalışma zamanında eksik anahtarı döndürür veya yapılandırmaya göre hata fırlatır
    Zengin içerik (JSX / Markdown / bileşenler)✅ Doğrudan destek⚠️ Eşleme bileşenleri ile t.rich() üzerinden
    ICU MessageFormat desteği⚠️ Geliştirilmekte✅ Evet, tam ICU desteği
    Eşzamanlı sunucu bileşenlerinext-intlayer/server altındaki useIntlayer alt sunucu bileşenlerinde çalışır❌ Asenkron sunucu ebeveyninden props yoluyla çevirilerin aktarılmasını gerektirir
    Tree-shaking✅ Bileşen ve dil başına derleyici tarafından otomatik⚠️ Ad alanlarını manuel bölmeyi ve pick() kullanmayı gerektirir
    Tembel yükleme (Lazy loading)✅ Tek satır yapılandırma (importMode: 'dynamic')⚠️ getRequestConfig içinde manuel dinamik import gerektirir
    Görsel Düzenleyici / CMS✅ Ücretsiz Görsel Düzenleyici + isteğe bağlı CMS❌ Yok
    Yapay zeka destekli çeviri✅ Yerleşik, kendi sağlayıcı anahtarlarınızı kullanır❌ Yok
    MCP sunucusu ve Ajan Becerileri✅ Evet❌ Yok

    Karşılaştırmalı test

    Neler ölçüldü?

    Benchmark Bloom test paketi, her kütüphane ile aynı uygulamayı derler: 10 sayfa (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 dil (en, fr, es, de, it, pt, zh, ja, ko, ru), özdeş bileşenler ve özdeş içerik. Sayfalar en ve fr dillerinde ölçülür. Her kütüphane dört yükleme stratejisi ile test edilmiştir:

    StratejiAçıklamaKimler kullanır
    staticHer dil ve her sayfa baştan paketlenir ve yüklenirHızlı prototipler, yapay zeka kodları
    dynamicYalnızca etkin dil yüklenir, ancak tüm sayfalar birlikte gelirProjelerin büyük çoğunluğu
    scoped-staticRota başına ad alanları, tembel yükleme yokNadir
    scoped-dynamicRota başına ad alanları + tembel yükleme. Yalnızca geçerli dilin geçerli sayfası iletilirKatı performans bütçesi olan uygulamalar

    Intlayer'ın "scoped" varyantı yoktur: derleyici içeriği otomatik olarak bileşen başına sınırlar, bu nedenle static ve dynamic satırları zaten kapsamlandırılmıştır.

    Her derleme için şunlar kaydedilir:

    • Kütüphane boyutu (Lib size): Yalnızca i18n kütüphanesini içe aktaran boş bir bileşenin gzip boyutu.
    • Sayfa JS (Page JS): Sayfa başına indirilen gzip sıkıştırmalı JavaScript.
    • Dil sızıntısı % (Locale leak %): Kullanıcının görüntülemediği bir dile ait dizgilerin oranı.
    • Sayfa sızıntısı % (Page leak %): Kullanıcının üzerinde bulunmadığı bir sayfaya ait dizgilerin oranı.
    • Bileşen ortalaması (Component avg): Yalıtılmış olarak derlenen her bileşenin ortalama gzip boyutu.
    • E2E tepkisellik: Dil değişiminden DOM'daki html[lang] güncellenmesine kadar geçen süre.
    • Hidrasyon: React hidrasyon aşamasının süresi.
    Aşağıdaki veriler next-intl 4.14.2 ve intlayer 9.5.1 ile 2026-09-12 tarihindeki çalıştırmadan alınmıştır.

    Next.js (App Router) Sonuçları

    KütüphaneStratejiKütüphane Boyutu (gz)Ort. Sayfa JS (gz)Dil SızıntısıSayfa SızıntısıOrt. Bileşen (gz)E2E TepkisellikHidrasyon
    Temel uygulama (i18n yok)-0.0 KB141.0 KB0.0%0.0%0.9 KB13.4 ms11.8 ms
    next-intlstatic14.7 KB153.6 KB4.2%89.8%21.8 KB16.0 ms14.7 ms
    next-intldynamic14.7 KB153.6 KB9.7%89.9%21.8 KB15.6 ms14.8 ms
    next-intlscoped-static14.7 KB153.6 KB0.0%0.0%80.1 KB17.9 ms17.4 ms
    next-intlscoped-dynamic14.7 KB153.6 KB0.0%0.0%22.9 KB17.8 ms16.8 ms
    next-intlayerstatic5.5 KB141.3 KB0.0%0.0%8.5 KB15.5 ms16.9 ms
    next-intlayerdynamic5.5 KB141.3 KB0.0%0.0%6.9 KB15.3 ms15.9 ms
    @intlayer/next-intl (uyumlu)static8.0 KB147.5 KB0.0%0.0%8.1 KB14.5 ms12.8 ms
    @intlayer/next-intl (uyumlu)dynamic8.0 KB148.7 KB0.0%0.0%8.1 KB11.7 ms12.8 ms

    Sonuçlar nasıl okunmalı?

    • Çalışma zamanı maliyeti. Temel uygulama sayfa başına 141.0 KB'dir. next-intl bunu 153.6 KB'ye çıkarırken (her sayfada +12.6 KB gzip), Intlayer yalnızca 141.3 KB (+0.3 KB) yer kaplar.
    • İçerik sızıntısı. En yaygın kurulumlarda (static ve dynamic), next-intl tüm en.json istemci sağlayıcısına girdiği için her sayfada diğer sayfaların içeriğinin yaklaşık %90'ını gönderir. Bunu %0'a indirmek zahmetli manuel ad alanı ayrımı gerektirir; Intlayer ise bunu varsayılan olarak sunar.
    • Bileşen boyutu. useTranslations() çağıran bir bileşen ortalama 21.8 KB derlenirken, useIntlayer() kullanan aynı bileşen sadece 6.9 KB tutar.

    TanStack Start (use-intl) Sonuçları

    KütüphaneStratejiKütüphane Boyutu (gz)Ort. Sayfa JS (gz)Dil SızıntısıSayfa SızıntısıOrt. Bileşen (gz)E2E Tepkisellik
    Temel uygulama (i18n yok)-0.0 KB111.0 KB0.0%0.0%0.7 KB8.1 ms
    use-intlstatic14.1 KB179.8 KB50.0%89.8%76.0 KB6.7 ms
    use-intldynamic14.1 KB119.4 KB0.0%89.8%75.9 KB7.0 ms
    use-intlscoped-static14.1 KB128.7 KB0.0%0.0%87.1 KB20.9 ms
    use-intlscoped-dynamic14.1 KB128.7 KB0.0%0.0%87.1 KB13.3 ms
    intlayerstatic5.0 KB125.8 KB50.0%0.0%8.1 KB3.2 ms
    intlayerdynamic5.0 KB118.6 KB0.0%0.0%6.3 KB3.6 ms
    @intlayer/use-intl (uyumlu)dynamic7.3 KB129.7 KB0.0%0.0%9.3 KB8.7 ms

    Sonuçlar nasıl okunmalı?

    • Basit use-intl kurulumu, temel uygulamaya göre sayfa başına 68.8 KB daha fazla JS iletir.
    • dynamic modda use-intl 119.4 KB değerine inse de %89.8 sayfa sızıntısını sürdürür.
    • Mimari fark en çok bileşen boyutunda göze çarpar: use-intl ile 76-87 KB, Intlayer ile 6-8 KB.
    • Dil değiştirme hızı Intlayer ile 2-4 kat daha seridir (3 ms vs 7-21 ms).

    Neden bu fark var? Merkezi kataloglar vs derlenmiş sözlükler

    next-intl geleneksel modeli izler: dil başına bir JSON, getRequestConfig içinde yüklenir, NextIntlClientProvider'a aktarılır ve t("namespace.key") ile okunur.

    bash
    .
    ├── messages
       ├── en.json
       └── fr.json
    └── src
        ├── i18n
       ├── request.ts
       └── routing.ts
        ├── middleware.ts
        └── app
            └── [locale]
                ├── layout.tsx
                └── about
                    └── page.tsx
    

    Çalışma zamanı bir sayfanın hangi anahtarları kullanacağını bilemez, bu yüzden tüm kataloğu göndermek en güvenli yoldur.

    Intlayer bu sorumluluğu tersine çevirir. İçerik doğrudan ilgili bileşenin yanında tanımlanır:

    bash
    .
    ├── intlayer.config.ts
    └── src
        ├── middleware.ts
        └── app
            └── [locale]
                ├── layout.tsx
                └── about
                    ├── page.tsx
                    └── page.content.ts
        └── components
            └── Counter
                ├── index.tsx
                └── index.content.ts
    

    Derleme sırasında derleyici, hangi bileşenin hangi sözlüğü içe aktardığını tespit eder ve yalnızca etkin dil için gereken sözlükleri paketler.

    dynamic satırının verilerini elde etmek için intlayer.config.ts dosyasında dictionary.importMode: 'dynamic' ayarını yapın. Paket optimizasyonu belgesine göz atın.

    Geliştirici deneyimi

    İstemci bileşeni (Client component)

    next-intl

    messages/en.json
    {
      "counter": {
        "label": "Counter",
        "increment": "Increment"
      }
    }
    
    src/components/Counter.tsx
    "use client";
    
    import { useState } from "react";
    import { useTranslations, useFormatter } from "next-intl";
    
    export const Counter = () => {
      const t = useTranslations("counter");
      const format = useFormatter();
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>{format.number(count)}</p>
          <button aria-label={t("label")} onClick={() => setCount((c) => c + 1)}>
            {t("increment")}
          </button>
        </div>
      );
    };
    

    Intlayer

    src/components/Counter/index.content.ts
    import { t, type Dictionary } from "intlayer";
    
    const counterContent = {
      key: "counter",
      content: {
        label: t({ en: "Counter", fr: "Compteur" }),
        increment: t({ en: "Increment", fr: "Incrémenter" }),
      },
    } satisfies Dictionary;
    
    export default counterContent;
    
    src/components/Counter/index.tsx
    "use client";
    
    import { useState } from "react";
    import { useIntlayer } from "next-intlayer";
    import { useNumber } from "next-intlayer/format";
    
    export const Counter = () => {
      const { label, increment } = useIntlayer("counter");
      const number = useNumber();
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label} onClick={() => setCount((c) => c + 1)}>
            {increment}
          </button>
        </div>
      );
    };
    

    Eşzamanlı sunucu bileşenleri

    Tasarım sistemi bileşenleri (navbar, footer, kartlar) genellikle istemci bileşenlerinin alt öğeleri olarak işlenen sunucu bileşenleridir, dolayısıyla async olamazlar.

    next-intl

    src/components/ServerCounter.tsx
    type ServerCounterProps = {
      t: (key: string) => string;
      formattedCount: string;
    };
    
    export const ServerCounter = ({ t, formattedCount }: ServerCounterProps) => (
      <div>
        <p>{formattedCount}</p>
        <button aria-label={t("label")}>{t("increment")}</button>
      </div>
    );
    

    Intlayer

    src/components/ServerCounter.tsx
    import { useIntlayer } from "next-intlayer/server";
    import { useNumber } from "next-intlayer/server/format";
    
    export const ServerCounter = ({ count }: { count: number }) => {
      const { label, increment } = useIntlayer("counter");
      const number = useNumber();
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label}>{increment}</button>
        </div>
      );
    };
    

    Meta veriler (Metadata)

    next-intl

    src/app/[locale]/about/page.tsx
    import type { Metadata } from "next";
    import { getTranslations } from "next-intl/server";
    import { routing } from "@/i18n/routing";
    
    const localizedPath = (locale: string, path: string) =>
      locale === routing.defaultLocale ? path : `/${locale}${path}`;
    
    export const generateMetadata = async ({
      params,
    }: {
      params: Promise<{ locale: string }>;
    }): Promise<Metadata> => {
      const { locale } = await params;
      const t = await getTranslations({ locale, namespace: "about" });
    
      const languages = Object.fromEntries(
        routing.locales.map((l) => [l, localizedPath(l, "/about")])
      );
    
      return {
        title: t("title"),
        description: t("description"),
        alternates: {
          canonical: localizedPath(locale, "/about"),
          languages: { ...languages, "x-default": "/about" },
        },
      };
    };
    

    Intlayer

    src/app/[locale]/about/page.tsx
    import { getIntlayer, getMultilingualUrls } from "intlayer";
    import type { Metadata } from "next";
    import type { LocalPromiseParams } from "next-intlayer";
    
    export const generateMetadata = async ({
      params,
    }: LocalPromiseParams): Promise<Metadata> => {
      const { locale } = await params;
      const metadata = getIntlayer("about-metadata", locale);
      const multilingualUrls = getMultilingualUrls("/about");
    
      return {
        ...metadata,
        alternates: {
          canonical: multilingualUrls[locale as keyof typeof multilingualUrls],
          languages: { ...multilingualUrls, "x-default": "/about" },
        },
      };
    };
    

    next-intl API'sini koruyun, Intlayer verimini elde edin

    Yukarıdaki performans verilerine ulaşmak için bileşenlerinizi sıfırdan yazmanız gerekmez. @intlayer/next-intl doğrudan tak-çalıştır bir adaptördür: useTranslations, getTranslations, useFormatter, t.rich() ve ICU çoğul yapılarını korur, bunları Intlayer derleyicisi tarafından derlenen Intlayer sözlüklerinden sunar.

    next.config.ts
    import type { NextConfig } from "next";
    import { createNextIntlPlugin } from "@intlayer/next-intl/plugin";
    
    const withIntlayer = createNextIntlPlugin();
    
    const nextConfig: NextConfig = {};
    
    export default withIntlayer(nextConfig);
    

    Testlerde, aynı uygulamanın uyumluluk derlemesi, uygulama koduna dokunulmadan sayfa başına 153.6 KB'den 147.5 KB'ye, bileşen başına 21.8 KB'den 8.1 KB'ye ve sayfa sızıntısında %90'dan %0'a geriledi. Mevcut messages/{locale}.json dosyalarınız JSON eşitleme eklentisi ile tek doğruluk kaynağı olarak kalabilir.

    Ayrıntılı adımlar için next-intl geçiş kılavuzuna göz atın.

    Hangisi ne zaman tercih edilmeli?

    • next-intl tercih edin: Next.js ekosisteminin yaygın standartlarını istiyorsanız, ICU MessageFormat'a yoğun şekilde güveniyorsanız, uygulamanız küçük veya orta ölçekliyse veya merkezi JSON bekleyen çeviri platformlarıyla (Crowdin, Phrase, Lokalise...) entegreyseniz.
    • Intlayer tercih edin: Bileşen kapsamlı içerik, katı TypeScript desteği, derleme zamanı eksik anahtar tespiti, sıfır yapılandırmalı tree-shaking ve tembel yükleme, eşzamanlı sunucu bileşenleri ve yerleşik düzenleme araçları (Görsel Düzenleyici, CMS, yapay zeka çevirisi, MCP sunucusu) istiyorsanız.
    • @intlayer/next-intl tercih edin: Halihazırda next-intl kullanıyorsanız ve kodu yeniden yazmadan paket boyutu kazanımı elde etmek istiyorsanız.

    İlgili karşılaştırmalar

    GitHub Yıldızları

    GitHub yıldızları, bir projenin popülaritesinin ve topluluk güveninin önemli bir göstergesidir.

    Yıldız Geçmişi Grafiği

    Sonuç

    next-intl, Next.js üzerinde güvenilir ve sağlam bir kütüphanedir. Ancak merkezi katalog modeli optimizasyon yükünü geliştiriciye bırakır: basit bir kurulum diğer sayfaların içeriğinin yaklaşık %90'ını sızdırır ve çalışma zamanının kendisi her sayfada +12.6 KB gzip ekler.

    Intlayer bu yükü derleyiciye devreder. Bileşen başına sözlükler, dil başına tembel yükleme ve gereksiz içeriklerin temizlenmesi otomatik derleme çıktısıdır. Aynı uygulamadaki sonuç: sayfa başına +0.3 KB, %0 sızıntı, 3 kat daha küçük bileşenler ve TanStack Start üzerinde 2-4 kat daha hızlı dil değişimi.

    Tüm ham veriler, test uygulamaları ve betikler Benchmark Bloom deposunda yer almaktadır.

    Daha fazla ayrıntı için 'Neden Intlayer?' belgesine bakın.

    Yorumlar

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

    İlgili Gönderiler

    Son Gönderiler