Penulis:
    Dibuat:2026-09-13Terakhir diperbarui:2026-09-27

    Lingui VS Intlayer: Tolok Ukur Internasionalisasi (i18n) React & Next.js

    Lingui dan Intlayer adalah dua pustaka dalam tolok ukur ini yang mengandalkan kompiler daripada runtime murni. Lingui mengekstrak pesan dari makro saat build time dan mengompilasi katalog per lokal. Intlayer mengompilasi kamus per komponen dan melakukan tree-shake per lokal. Di atas kertas keduanya seharusnya sebanding. Angka-angka berikut menunjukkan di mana keduanya berbeda.

    Data berasal dari Benchmark Bloom, sebuah rangkaian pengujian sumber terbuka yang membangun aplikasi yang sama dengan masing-masing pustaka dan mencatat apa yang sebenarnya diunduh serta dieksekusi oleh peramban.

    tl;dr: Lingui paling mendekati Intlayer dalam hal JavaScript mentah per halaman: 115-120 KB vs 118.6 KB pada TanStack Start setelah lazy loading dikonfigurasi, 148.6 KB vs 141.3 KB pada Next.js. Namun celah melebar di aspek lain: komponen Lingui yang dikompilasi secara terisolasi berukuran 58-153 KB dibandingkan 6-8 KB untuk Intlayer, hidrasi membutuhkan 28-34 ms dibandingkan 11-14 ms, fallback lokal sumber membocorkan 3-15% string en ke halaman fr di setiap pengaturan optimal, dan mencapai pengaturan optimal tersebut membutuhkan ekstraksi, kompilasi, serta pemilihan katalog secara manual per rute. Intlayer mencapainya tanpa konfigurasi tambahan.

    Ringkasan

    • Lingui - Berbasis makro ( t`...` , <Trans>, msg), ICU MessageFormat, katalog .po / JSON, alur kerja lingui extract + lingui compile. Mengompilasi ID pesan menjadi hash pendek, mendukung pemuatan katalog dinamis per lokal. Sangat mapan, agnostik kerangka kerja, dukungan ekosistem penerjemah yang kuat seputar file .po.
    • Intlayer - Model konten yang berpusat pada komponen. Kamus .content.ts ditempatkan berdampingan dengan komponen yang dilayaninya, kompiler build-time melakukan tree-shake dan lazy-load per komponen dan per lokal, tipe TypeScript yang ketat dihasilkan dari konten Anda, dan terjemahan yang hilang gagal pada saat build. Menyertakan middleware terintegrasi, pembantu SEO, Visual Editor / CMS, dan terjemahan berbantuan AI.
    PustakaBintang GitHubTotal KomitKomit TerakhirVersi PertamaVersi NPMUnduhan NPM
    aymericzip/intlayerGitHub Repo starsGitHub commit activityLast CommitApril 2024npmnpm downloads
    lingui/js-linguiGitHub Repo starsGitHub commit activityLast CommitDes 2016npmnpm downloads
    Lencana diperbarui secara otomatis. Cuplikan data akan bervariasi seiring waktu.

    Perbandingan fitur berdampingan

    FiturIntlayer (react-intlayer / next-intlayer)Lingui (@lingui/core / @lingui/react)
    Terjemahan dekat komponen✅ Ya, .content.ts ditempatkan bersama setiap komponen⚠️ String sumber inline di JSX via makro; terjemahan dalam katalog .po terpusat
    Integrasi TypeScript✅ Tipe ketat dihasilkan otomatis dari konten⚠️ Makro memiliki tipe; ID pesan tidak, entri katalog yang hilang tidak terdeteksi
    Deteksi terjemahan yang hilang✅ Error TypeScript + error/peringatan saat build⚠️ lingui extract melaporkan statistik; runtime beralih ke string sumber
    Konten kaya (JSX / Markdown / komponen)✅ Dukungan langsung✅ <Trans> dengan komponen bersarang
    Dukungan ICU⚠️ Sedang dikembangkan✅ Ya (makro plural, select, selectOrdinal)
    Pemformatan (tanggal, angka, mata uang)✅ useNumber, useDate, ... (Intl bawaan)✅ i18n.date(), i18n.number()
    Routing terlokalisasi & middleware✅ Proxy/middleware bawaan, getMultilingualUrls❌ Bukan inti
    Pembantu SEO (hreflang, sitemap, robots)✅ Pembantu bawaan❌ Manual
    Komponen server sinkron✅ useIntlayer dari next-intlayer/server berfungsi di semua komponen server turunan⚠️ Memerlukan instans I18n per permintaan, diteruskan ke bawah atau diatur via setI18n
    Tree-shaking (hanya kirim konten terpakai)✅ Per komponen, per lokal, diotomatisasi oleh kompiler⚠️ Per lokal via lingui compile; per rute memerlukan pemisahan katalog manual
    Pemuatan lambat (Lazy loading)✅ importMode: 'dynamic' (satu baris konfigurasi)⚠️ import() manual katalog terkompilasi + i18n.load() / i18n.activate()
    Hapus konten yang tidak digunakan✅ Kamus yang tidak terpakai dibuang saat build✅ lingui extract --clean menghapus pesan yang usang
    Uji terjemahan yang hilang (CLI / CI)✅ npx intlayer content test⚠️ Statistik lingui extract (tanpa kode keluar error secara default)
    Pipeline build✅ Satu plugin (@intlayer/swc / @intlayer/babel / vite-intlayer)⚠️ Plugin makro (Babel atau SWC) + langkah extract + compile
    Terjemahan bertenaga AI✅ Bawaan, menggunakan kunci penyedia Anda sendiri❌ Tidak
    Visual Editor / CMS✅ Visual Editor gratis + CMS opsional❌ Tidak (.po bekerja dengan TMS eksternal)
    Server MCP & Keterampilan Agen✅ Ya❌ Tidak
    Ekosistem / komunitas⚠️ Lebih kecil tetapi berkembang pesat✅ Mapan, agnostik kerangka kerja

    Tolok ukur

    Apa yang diukur

    Rangkaian Benchmark Bloom membangun aplikasi yang sama dengan setiap pustaka: 10 halaman (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 lokal (en, fr, es, de, it, pt, zh, ja, ko, ru), komponen identik, dan konten identik. Halaman diukur dalam en dan fr. Setiap pustaka diuji hingga empat strategi pemuatan, dari konfigurasi paling sederhana hingga optimal:

    StrategiDeskripsiSiapa yang menggunakan
    staticKatalog terkompilasi dari setiap lokal diimpor dan dimuat di awalPrototipe cepat, kode hasil AI
    dynamicHanya katalog lokal aktif yang diimpor via import(), tetapi mencakup semua halamanMayoritas proyek
    scoped-staticSatu katalog per rute, semuanya dibundel di awalJarang
    scoped-dynamicSatu katalog per rute + import() dinamis. Hanya halaman aktif, lokal aktifAplikasi dengan anggaran kinerja ketat

    Intlayer tidak memerlukan varian "scoped": kompiler otomatis membatasi konten per komponen, sehingga baris static dan dynamic sudah ter-scope secara bawaan.

    Untuk setiap build, pengujian mencatat:

    • Ukuran pustaka (Lib size): ukuran gzip dari komponen kosong yang hanya mengimpor pustaka i18n. Biaya tetap runtime.
    • JS Halaman (Page JS): JavaScript terkompresi gzip per halaman, dirata-ratakan di seluruh halaman dan lokal.
    • % kebocoran lokal (Locale leak %): proporsi string terjemahan dalam JS terunduh yang berasal dari lokal yang tidak sedang dilihat pengguna (diuji pada en dan fr, sehingga 50% berarti "lokal terukur lainnya ada sepenuhnya"; dengan 10 lokal terbundel, pemborosan sebenarnya jauh lebih tinggi).
    • % kebocoran halaman (Page leak %): proporsi string terjemahan dalam JS terunduh yang berasal dari halaman yang tidak sedang diakses pengguna.
    • Rata-rata komponen (Component avg): ukuran gzip rata-rata dari setiap komponen yang dikompilasi secara terisolasi. Menunjukkan seberapa besar runtime i18n dan katalog yang diseret oleh satu komponen.
    • Reaktivitas E2E: waktu antara memilih lokal baru hingga pembaruan html[lang] di DOM (Playwright, 5 iterasi).
    • Hidrasi: durasi fase hidrasi React.
    Angka-angka di bawah ini berasal dari pengujian tanggal 2026-09-12 menggunakan @lingui/react 6.6.0 dan intlayer 9.5.1. Aplikasi pengujian sengaja dibuat kecil (beberapa lusin string per lokal), sehingga persentase kebocoran menggambarkan sebuah pola: angka ini meningkat seiring bertambahnya konten Anda sementara biaya runtime tetap konstan.

    Hasil pada Next.js

    Pilih metrik dan pustaka yang Anda minati:

    Metrik

    Pemuatan JSON dinamis

    Memuat terjemahan secara lambat saat runtime

    JSON cakupan (namespacing)

    Namespace terjemahan per halaman

    Apa metrik ini?

    Total ukuran kompresi gzip dari bundel pustaka internasionalisasi. Ini hanya mencakup penyedia dan logika pengambilan konten setelah tree-shaking dan minifikasi.

    Mengapa ini penting?

    Ukuran pustaka yang lebih kecil mengurangi muatan JavaScript awal, yang mengarah pada waktu unduh dan eksekusi yang lebih cepat pada klien.

    Lihat sebagai

    PustakaStrategiUkuran Lib (gz)Rata-rata JS Halaman (gz)Bocor LokalBocor HalamanRata-rata Komponen (gz)Reaktivitas E2EHidrasi
    base (tanpa i18n)-0.0 KB141.0 KB0.0%0.0%0.9 KB13.4 ms11.8 ms
    Linguistatic11.9 KB207.4 KB50.0%90.0%73.3 KB15.3 ms15.2 ms
    Linguidynamic11.9 KB145.4 KB2.8%89.9%19.9 KB15.7 ms12.7 ms
    Linguiscoped-static11.9 KB148.2 KB2.7%89.1%20.4 KB15.1 ms13.1 ms
    Linguiscoped-dynamic11.9 KB148.6 KB14.8%0.0%152.6 KB16.1 ms14.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

    Cara membaca hasil

    • Biaya runtime. Komponen kosong membutuhkan 11.9 KB gzip dengan Lingui, dibandingkan 5.5 KB dengan Intlayer. Pada halaman penuh, konfigurasi terbaik Lingui berada pada +7.3 KB di atas Intlayer (148.6 vs 141.3 KB); Intlayer hanya bertambah +0.3 KB di atas aplikasi dasar.
    • Konfigurasi sederhana berbiaya mahal. Memuat setiap katalog terkompilasi di awal menghasilkan 207.4 KB per halaman, +66 KB di atas aplikasi dasar. Setengah dari string yang diuji berasal dari lokal yang salah, dan 90% dari halaman yang salah.
    • Pemuatan dinamis memperbaiki lokal, bukan halaman. Dengan satu katalog per lokal, kebocoran halaman tetap berada pada ~90%: seluruh katalog fr dikirimkan pada setiap halaman berbahasa Prancis. Untuk mencapai 0% kebocoran halaman, diperlukan pengaturan scoped-dynamic: satu katalog per rute, diekstrak dan dikompilasi secara terpisah, serta dipilih secara manual pada setiap halaman.
    • Fallback lokal sumber bocor. Bahkan dalam pengaturan yang dioptimalkan, 3-15% string en tetap terkirim di dalam halaman fr. Makro Lingui menjaga pesan sumber tetap tersedia sebagai fallback, sehingga ikut masuk ke dalam bundle bersama terjemahan. Intlayer menyelesaikan fallback pada saat build dan hanya mengirimkan lokal yang aktif.
    • Ukuran komponen membengkak pada scoped-dynamic. Setiap komponen yang dikompilasi secara terisolasi rata-rata berukuran 152.6 KB, karena katalog setiap rute dapat diakses dari komponen yang mengimpornya. Komponen yang sama dengan useIntlayer() hanya berukuran rata-rata 6.9 KB.
    Tabel lengkap, setiap pustaka dan setiap strategi, dalam laporan tolok ukur Next.js.

    Hasil pada TanStack Start

    PustakaStrategiUkuran Lib (gz)Rata-rata JS Halaman (gz)Bocor LokalBocor HalamanRata-rata Komponen (gz)Reaktivitas E2EHidrasi
    base (tanpa i18n)-0.0 KB111.0 KB0.0%0.0%0.7 KB8.1 ms21.6 ms
    Linguistatic11.2 KB152.2 KB50.0%90.0%58.0 KB3.9 ms19.9 ms
    Linguidynamic11.2 KB115.2 KB9.3%0.0%85.5 KB5.9 ms28.0 ms
    Linguiscoped-static11.2 KB120.8 KB4.0%0.0%147.9 KB7.1 ms33.9 ms
    Linguiscoped-dynamic11.2 KB120.2 KB8.6%0.0%83.7 KB42.1 ms32.9 ms
    intlayerstatic5.0 KB125.8 KB50.0%0.0%8.1 KB3.2 ms11.5 ms
    intlayerdynamic5.0 KB118.6 KB0.0%0.0%6.3 KB3.6 ms14.1 ms
    @intlayer/lingui (kompat)dynamic10.3 KB137.0 KB9.9%0.0%12.8 KB2.9 ms19.7 ms

    Cara membaca hasil

    • Dalam hal JavaScript per halaman, Lingui unggul tipis. dynamic Lingui mencapai 115.2 KB, 3.4 KB di bawah Intlayer (118.6 KB). Katalog terkompilasi Lingui dengan hash ID sangat ringkas, dan router TanStack Start membagi rute dengan sangat baik sehingga kebocoran halaman sudah 0% pada baris dynamic.
    • Segala hal lainnya berpihak pada Intlayer. Hidrasi membutuhkan waktu 28-34 ms pada Lingui berbanding 11-14 ms pada Intlayer: i18n.load() + i18n.activate() dijalankan di klien sebelum React dapat melakukan hidrasi. Komponen yang dikompilasi secara terisolasi berukuran 58-148 KB berbanding 6-8 KB. Kebocoran lokal tidak pernah mencapai 0% (4-9%) karena fallback lokal sumber.
    • Pergantian lokal pada pengaturan teroptimasi berlangsung lambat. scoped-dynamic Lingui membutuhkan waktu 42 ms untuk memperbarui html[lang]: katalog rute baru harus diambil, dimuat, dan diaktifkan sebelum perubahan terlihat. Intlayer beralih dalam 3-4 ms pada kedua mode.
    • Baris static Intlayer sudah memiliki 0% kebocoran halaman karena hanya kamus yang diimpor oleh komponen halaman yang dibundel. Satu baris konfigurasi (importMode: 'dynamic') menghapus kebocoran lokal juga.
    • @intlayer/lingui mempertahankan sintaks makro Lingui dan menyajikannya dari kamus Intlayer. Pendekatan ini mengorbankan sedikit ukuran halaman (137 KB, karena runtime makro tetap ada) demi komponen yang lebih kecil (12.8 KB) dan hidrasi yang lebih cepat daripada Lingui bawaan. Ini adalah langkah migrasi, bukan tujuan akhir.
    Tabel lengkap dalam laporan tolok ukur TanStack Start.

    Mengapa ada perbedaan? Dua kompiler, dua unit kerja

    The Intlayer compiler extracts content from components

    Kedua pustaka melakukan kompilasi. Perbedaannya terletak pada apa yang mereka kompilasi.

    Lingui mengompilasi katalog. Makro dalam kode sumber Anda diekstrak ke dalam file .po per lokal, lalu dikompilasi menjadi modul JS per lokal. Unit kerjanya adalah lokal. Membaginya lebih lanjut, berdasarkan rute atau komponen, berarti membuat beberapa katalog, mengonfigurasi lingui.config.ts untuk mengekstrak masing-masing dari kumpulan file yang berbeda, dan memuat katalog yang tepat di setiap rute. Instans runtime I18n bersifat global; setiap pemanggilan useLingui() menghubungkan komponen ke instans tersebut.

    bash
    .
    ├── lingui.config.ts
    └── src
        ├── i18n.ts                          # setupI18n(), load(), activate()
        ├── locales
        │   ├── en
        │   │   ├── messages.po
        │   │   └── messages.mjs             # output lingui compile
        │   └── fr
        │       ├── messages.po
        │       └── messages.mjs
        ├── components
        │   └── Counter.tsx                  # const { t } = useLingui(); t`Increment`
        └── routes
            └── $locale
                └── about.tsx                # await import(`../locales/${locale}/messages.mjs`)
    

    Intlayer mengompilasi kamus. Setiap file .content.ts adalah kamus yang terikat pada sebuah kunci; kompiler mencari tahu komponen mana yang mengimpor kunci tersebut dan menghasilkan, per kamus dan per lokal, tepatnya JSON yang dibutuhkan komponen tersebut. Unit kerjanya adalah komponen. Pembatasan rute adalah konsekuensi alaminya: suatu halaman hanya menarik kamus dari komponen yang direndernya.

    bash
    .
    ├── intlayer.config.ts
    └── src
        ├── components
        │   └── Counter
        │       ├── index.tsx                # useIntlayer("counter")
        │       └── index.content.ts
        └── routes
            └── $locale
                ├── about.tsx
                └── about.content.ts
    

    Itulah mengapa pola scoped-dynamic adalah output bawaan bagi Intlayer dan merupakan proyek konfigurasi manual yang rumit bagi Lingui. Kesenjangan melebar pada dua sumbu sekaligus, halaman dan bahasa:

    Theoretical content leakage by architecture

    Untuk mendapatkan angka pada baris dynamic, atur dictionary.importMode: 'dynamic' di intlayer.config.ts. Lihat panduan optimasi bundle.

    Pengalaman pengembang

    Pengaturan

    lingui.config.ts
    import { defineConfig } from "@lingui/cli";
    
    export default defineConfig({
      sourceLocale: "en",
      locales: ["en", "fr"],
      catalogs: [
        {
          path: "<rootDir>/src/locales/{locale}/messages",
          include: ["src"],
        },
      ],
    });
    
    src/i18n.ts
    import { setupI18n } from "@lingui/core";
    
    export const loadCatalog = async (locale: string) => {
      const { messages } = await import(`./locales/${locale}/messages.mjs`);
      const i18n = setupI18n();
      i18n.load(locale, messages);
      i18n.activate(locale);
      return i18n;
    };
    

    Kemudian tambahkan @lingui/babel-plugin-lingui-macro (atau @lingui/swc-plugin) ke bundler, jalankan lingui extract setelah mengedit kode sumber, jalankan lingui compile sebelum build, dan bungkus hierarki aplikasi dengan <I18nProvider i18n={i18n}>.

    intlayer.config.ts
    import { type IntlayerConfig, Locales } from "intlayer";
    
    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH],
        defaultLocale: Locales.ENGLISH,
      },
    };
    
    export default config;
    

    Tambahkan intlayer() ke vite.config.ts (atau withIntlayer() ke next.config.ts) dan bungkus hierarki komponen dengan <IntlayerProvider>. Tidak ada langkah ekstrak atau kompilasi terpisah: kamus dibangun secara otomatis saat bundler berjalan.

    Komponen

    src/components/Counter.tsx
    import { useState } from "react";
    import { useLingui } from "@lingui/react/macro";
    import { Trans } from "@lingui/react/macro";
    
    export const Counter = () => {
      const { t, i18n } = useLingui();
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>{i18n.number(count)}</p>
          <button aria-label={t`Counter`} onClick={() => setCount((c) => c + 1)}>
            <Trans>Increment</Trans>
          </button>
        </div>
      );
    };
    

    Teks bahasa Inggris berada di dalam komponen; teks bahasa Prancis berada di src/locales/fr/messages.po di bawah ID ter-hash, setelah lingui extract dijalankan. Jika Anda lupa menjalankannya atau lupa menjalankan compile, aplikasi akan secara diam-diam kembali ke bahasa Inggris.

    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
    import { useState } from "react";
    import { useIntlayer } from "react-intlayer";
    import { useNumber } from "react-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>
      );
    };
    

    Kedua lokal berada dalam satu file di samping komponen. Nilai fr yang hilang akan memicu error saat build, dan kunci yang salah akan menjadi error TypeScript.

    Di luar komponen

    Metadata, loader, fungsi server: di mana saja tanpa hierarki React.

    src/routes/$locale/about.tsx
    import { setupI18n } from "@lingui/core";
    import { msg } from "@lingui/core/macro";
    
    const title = msg`About us`;
    
    export const loader = async ({ params }: { params: { locale: string } }) => {
      const { messages } = await import(
        `../../locales/${params.locale}/messages.mjs`
      );
      const i18n = setupI18n({
        locale: params.locale,
        messages: { [params.locale]: messages },
      });
    
      return { title: i18n._(title) };
    };
    

    Instans I18n baru dibuat per pemanggilan, katalog yang tepat dimuat secara manual, serta menggunakan msg + i18n._() daripada t. Sebagaimana dicatat dalam catatan tolok ukur, mengetahui kapan harus menggunakan t, t` ` , i18n.t(), msg, atau <Trans> sering kali membingungkan.

    src/routes/$locale/about.tsx
    import { getIntlayer } from "intlayer";
    
    export const loader = async ({ params }: { params: { locale: string } }) => {
      const { title } = getIntlayer("about-metadata", params.locale);
    
      return { title };
    };
    

    Pertahankan makro Lingui, dapatkan kamus Intlayer

    @intlayer/lingui adalah adaptor pengganti langsung untuk @lingui/core dan @lingui/react. Makro tetap dikompilasi seperti biasa; pemanggilan runtime i18n._() yang dihasilkannya disajikan langsung dari kamus Intlayer, dengan plugin sinkronisasi .po yang menjaga katalog lama Anda tetap sinkron. Bentuk jamak dan seleksi ICU dirender secara identik.

    vite.config.ts
    import { defineConfig } from "vite";
    import { lingui } from "@intlayer/lingui/plugin";
    
    export default defineConfig({
      plugins: [lingui()],
    });
    

    Biarkan @lingui/babel-plugin-lingui-macro / @lingui/swc-plugin tetap berada dalam pipeline build sebelum kompiler Intlayer. Lihat dokumentasi kompatibilitas Lingui.

    Kapan harus memilih yang mana?

    Anda menginginkan ICU MessageFormat dengan makro bertipe, penerjemah Anda bekerja di .po dengan alur TMS yang ada, Anda lebih suka string sumber sebaris di JSX, dan tim Anda terbiasa mengelola alur kerja ekstrak / kompilasi / pemisahan katalog. JS per halamannya kompetitif setelah pemuatan lambat (lazy loading) diatur.

    Anda menginginkan konten dengan cakupan komponen, TypeScript yang ketat, kesalahan kunci yang hilang saat waktu build, tree-shaking dan pemuatan lambat tanpa usaha, komponen kecil, hidrasi cepat, pergantian bahasa instan, dan alat editorial bawaan (Editor Visual, CMS, terjemahan AI, server MCP). Sangat relevan untuk basis kode modular besar dan sistem desain.

    Anda menggunakan Lingui dan ingin beralih ke kamus Intlayer secara bertahap tanpa menyentuh makro. Katalog .po Anda tetap menjadi sumber kebenaran melalui plugin sinkronisasi PO. Diukur berdampingan dalam Lingui vs @intlayer/lingui.

    FAQ

    Karena unit kompilasinya berbeda. Lingui mengompilasi satu katalog per bahasa: segala sesuatu di bawahnya (katalog per rute, pemuatan lambat, menjaga fallback dari bundel) adalah konfigurasi manual. Intlayer mengompilasi satu kamus per komponen, sehingga pemisahan rute menjadi hasil langsung dari build. Itulah mengapa komponen Lingui yang dikompilasi secara terpisah berukuran 58-153 KB dibandingkan 6-8 KB pada Intlayer.

    Makro mempertahankan pesan sumber tersedia sebagai fallback runtime, sehingga string bahasa Inggris dikirim bersama terjemahannya. Tolok ukur mengukur 3-15% string en di dalam halaman fr di setiap pengaturan yang dioptimalkan. Intlayer menyelesaikan fallback pada waktu build dan hanya mengirim bahasa yang aktif.

    Ya, dan di TanStack Start ia menang tipis: 115.2 KB dalam mode dynamic dibandingkan 118.6 KB untuk Intlayer. Katalog yang dikompilasi dengan ID hash sangat ringkas. Biaya muncul di tempat lain: hidrasi pada 28-34 ms dibandingkan 11-14 ms, dan pergantian bahasa 42 ms dalam pengaturan scoped-dynamic.

    Tidak. @intlayer/lingui mempertahankan kompilasi t`...` , <Trans>, msg, plural, select, dan selectOrdinal seperti sebelumnya; hanya target resolusi i18n._() yang berubah. Pertahankan @lingui/babel-plugin-lingui-macro atau @lingui/swc-plugin dalam build. Lihat dokumentasi kompatibilitas Lingui.

    Langkah-langkah tersebut tetap ada untuk makro, dan hilang untuk konten asli Intlayer. Kamus .content.ts dibangun saat bundler berjalan, tanpa perintah CLI terpisah, dan intlayer test menggagalkan CI jika ada kunci yang hilang alih-alih secara diam-diam kembali ke string sumber.

    Perbandingan terkait

    JavaScript i18n library ecosystem

    Tolok ukur yang sama, pustaka lain:

    Lebih lanjut:

    Dokumen referensi:

    Untuk memahami asal-usul pustaka-pustaka ini, baca sejarah i18n di JavaScript.

    Bintang GitHub

    Bintang GitHub adalah indikator kuat dari popularitas proyek, kepercayaan komunitas, dan relevansi jangka panjang. Meskipun bukan pengukuran langsung terhadap kualitas teknis, metrik ini mencerminkan berapa banyak pengembang yang menganggap proyek ini bermanfaat dan mengikutinya.

    Grafik Riwayat Bintang

    Aktivitas commit

    Bintang menunjukkan popularitas. Commit menunjukkan seberapa banyak kerja yang masuk ke sebuah proyek. Saat tulisan ini dibuat, Intlayer memiliki sekitar 7.500 commit, lebih banyak dari sebagian besar library yang dibandingkan di sini, dan sekitar 5 kali lebih banyak dari next-intl atau next-i18next.

    • lingui/js-lingui
    • aymericzip/intlayer

    Commit pada branch default, sumber: GitHub API.

    Intlayer adalah monorepo, jadi jumlah ini mencakup setiap paket framework, CLI, dan dokumentasi. Baca commit sebagai sinyal aktivitas, bukan kualitas.

    Unduhan npm

    • @lingui/core
    • intlayer

    Sumber: API unduhan registri npm.

    Jumlah unduhan menghargai solusi yang paling lama, bukan yang terbaik. Library yang dirilis bertahun-tahun lalu masih diinstal oleh setiap proyek yang memilihnya saat itu, oleh setiap eksekusi CI, dan oleh setiap paket yang bergantung padanya. Angka ini lebih mengukur inersia daripada pilihan baru.

    Asisten AI memperkuat efek ini. next-intl, i18next, dan vue-i18n ada di mana-mana dalam kode yang menjadi data latih mereka, sehingga mereka menyarankannya secara default tanpa membandingkan alternatif. Setiap saran menambah unduhan, yang kemudian mendorong saran berikutnya. Bandingkan berdasarkan benchmark, bukan jumlah unduhan.

    Kesimpulan

    Lingui adalah pustaka kombinasi runtime dan kompiler terkuat dalam tolok ukur ini. Katalog terkompilasi dengan hash ID memberikan efisiensi JavaScript per halaman yang hampir menyamai Intlayer, bahkan sedikit lebih kecil di TanStack Start. Jika ukuran bita per halaman adalah satu-satunya ukuran, keduanya akan seri.

    Namun, bukan hanya itu yang penting. Kompiler Lingui hanya memproses hingga tingkat lokal; semua hal di bawahnya (katalog per rute, lazy loading, mencegah fallback bocor ke dalam bundle) adalah pekerjaan konfigurasi manual. Tolok ukur memperlihatkan biaya dari batasan tersebut: komponen 10-20x lebih besar, hidrasi 2-3x lebih lambat, kebocoran lokal 3-15% yang selalu ada, dan pergantian lokal memakan waktu 42 ms pada pengaturan optimal. Kompiler Intlayer bekerja pada tingkat komponen, sehingga angka-angka tersebut adalah 6-8 KB, 11-14 ms, 0%, dan 3-4 ms tanpa perlu konfigurasi tambahan.

    Semua data mentah, aplikasi pengujian, dan skrip tersedia di repositori Benchmark Bloom. Anda dapat menjalankannya sendiri.

    Lihat dokumen 'Mengapa Intlayer?' untuk informasi lebih lanjut.

    Komentar

    Belum ada komentar. Jadilah yang pertama membagikan pemikiran Anda.

    Postingan Terkait

    Postingan Terbaru