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

    vue-i18n VERSUS @intlayer/vue-i18n: API yang Sama, Bundle Berbeda

    @intlayer/vue-i18n adalah adapter kompatibilitas: ini mengekspos API vue-i18n (createI18n, useI18n, t(), d(), n(), $t, v-t, i18n.global.locale...) dan melayaninya dari kamus yang dikompilasi oleh Intlayer. File .vue Anda tidak berubah. Apa yang terikat pada t("footer.github") yang berubah.

    Artikel ini mengukur pertukaran tersebut pada aplikasi Vite + Vue 3 yang sama, dibangun sekali dengan vue-i18n dan sekali dengan adapter. Angka-angka tersebut berasal dari Benchmark Bloom. Untuk perbandingan vue-i18n dan Intlayer sebagai library, baca vue-i18n vs Intlayer dan benchmark vue-i18n vs Intlayer. Yang ini tentang apa yang berubah adapter ketika Anda mempertahankan komponen seperti apa adanya.

    tl;dr: Pada aplikasi Vite + Vue 3 yang sama, mengganti vue-i18n dengan @intlayer/vue-i18n mengurangi JavaScript per-halaman dari 134.9 KB menjadi 47.0 KB gzip (aplikasi tanpa i18n berukuran 41.3 KB), runtime dari 24.3 KB menjadi 7.9 KB, rata-rata komponen dari 196 KB menjadi 8.4 KB, dan kebocoran string halaman asing dari 90% menjadi 0%, tanpa mengedit file .vue apa pun. createI18n({ messages }) terus berfungsi sebagai fallback; hapus impor JSON untuk mendapatkan angka di atas. Blok SFC <i18n> dan setLocaleMessage() runtime adalah dua fitur yang tidak terbawa.

    Apa itu @intlayer/vue-i18n

    vue-i18n adalah runtime. createI18n({ messages: { en, fr, ... } }) membangun instans global yang menyimpan setiap pesan dari setiap lokal; useI18n() mengikat setiap komponen ke dalamnya; t("footer.github") menelusuri hierarki saat waktu render. Desain itulah yang memungkinkan blok SFC <i18n> dan setLocaleMessage(), dan itulah sebabnya grafik dependensi setiap komponen mencakup seluruh hierarki.

    @intlayer/vue-i18n mempertahankan API dan mengganti hierarki tersebut:

    1. Import aliasing. vueI18nVitePlugin() dari @intlayer/vue-i18n/plugin membungkus vite-intlayer dan menambahkan resolve.alias sehingga vue-i18n diselesaikan ke @intlayer/vue-i18n. Tidak ada impor yang diganti namanya.
    2. JSON sebagai sumber kebenaran. Plugin syncJSON membaca locales/{locale}.json Anda yang sudah ada dengan format: "vue-i18n" (sehingga interpolasi daftar {name}, {0} dan bentuk jamak "car | cars" diurai dengan benar) dan menulis kembali terjemahan saat CLI atau CMS memperbaruinya.
    3. Pengikatan call-site. Tahap optimalisasi Intlayer menulis ulang lokasi pemanggilan useI18n() sehingga komponen menerima kamus yang disebutkan oleh kuncinya, dalam lokal aktif, sebagai impor yang dapat dilacak dan dipecah oleh bundler.
    src/components/Footer.vue
    <!-- Kode Anda, tidak berubah -->
    <script setup lang="ts">
    import { useI18n } from "vue-i18n";
    
    const { t } = useI18n();
    </script>
    
    <template>
      <a href="https://github.com/intlayer-org/benchmark-bloom">{{
        t("footer.github")
      }}</a>
    </template>
    
    Apa yang dihasilkan kompiler (disederhanakan)
    import _dicHash_footer from "../.intlayer/dictionaries/footer.mjs";
    import { useDictionary as useI18n } from "@intlayer/vue-i18n";
    
    const { t } = useI18n(_dicHash_footer);
    

    Komponen tidak lagi mengakses hierarki pesan global. Komponen mengakses footer. Itulah sebabnya kolom ukuran komponen di bawah ini turun dari 196 KB menjadi 8 KB.

    Apa yang adapter simpan, abaikan, dan tidak gantikan

    API vue-i18nDengan @intlayer/vue-i18n
    useI18n() → { t, d, n, te, tm, rt, locale, availableLocales }✅ Dipertahankan. Kunci t memiliki tipe berdasarkan kamus Anda
    t("key", { name }), t("key", [a, b]), t("key", count)✅ Dipertahankan. {name}, {0} dan bentuk jamak dengan tanda pipa diselesaikan seperti sebelumnya
    d(date, "long"), n(value, "currency")✅ Dipertahankan. datetimeFormats / numberFormats dari createI18n() dihormati, didukung oleh Intl bawaan
    i18n.global.locale.value = "fr"✅ Dipertahankan. WritableComputedRef yang didukung oleh klien Intlayer; reaktivitas berfungsi seperti sebelumnya
    $t, $tc, $te, $tm, $rt, $d, $n, $i18n (Options API)✅ Dipertahankan. Didaftarkan di app.config.globalProperties oleh app.use(i18n)
    Direktif v-t✅ Dipertahankan
    legacy: true✅ Diterima
    createI18n({ messages })⚠️ messages digunakan sebagai fallback runtime dengan peringatan dev. Hapus impor JSON untuk penghematan bundle
    setLocaleMessage(), mergeLocaleMessage()❌ Peringatan dan tidak melakukan apa pun. Pemuatan pesan runtime digantikan oleh kamus saat build
    Blok kustom SFC <i18n>❌ Tidak dibaca. Pindahkan pesan-pesan tersebut ke dalam JSON lokal (atau .content.ts di sebelah komponen)
    @nuxtjs/i18n⚠️ Adapter terpisah, lihat dokumentasi kompatibilitas Nuxt

    Benchmark

    Apa yang diukur

    Rangkaian Benchmark Bloom membangun aplikasi Vite + Vue 3 yang sama dengan setiap konfigurasi: 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.

    Keduanya dibangun dalam konfigurasi statis, yang dikirimkan sebagian besar proyek Vue: untuk vue-i18n, JSON setiap lokal diimpor dan diteruskan ke createI18n({ messages }); untuk adapter, komponen yang sama dengan vite.config.ts dan intlayer.config.ts diubah dan impor messages dihapus. vue-intlayer native disertakan sebagai referensi.

    Untuk setiap build, pengujian mencatat:

    • Lib size: ukuran gzip (dan minified) dari komponen kosong yang hanya mengimpor library i18n.
    • Page JS: JavaScript gzip yang diunduh per halaman, dirata-ratakan di semua halaman dan lokal.
    • Locale leak %: bagian dari string terjemahan dalam JS yang diunduh milik lokal yang pengguna tidak lihat.
    • Page leak %: bagian dari string terjemahan dalam JS yang diunduh milik halaman tempat pengguna tidak berada.
    • Component avg: rata-rata ukuran gzip setiap komponen yang dikompilasi secara terisolasi.
    • E2E reactivity: waktu dari pemilihan lokal baru hingga lokal aktif dan html[lang] diperbarui di DOM (Playwright, 5 iterasi).
    • Page load: PerformanceNavigationTiming.duration.
    Angka-angka di bawah ini berasal dari pengujian tanggal 12-09-2026 dengan vue-i18n 11.4.0 dan @intlayer/vue-i18n 9.5.1. Aplikasi pengujian sengaja dibuat kecil (beberapa lusin string per lokal), sehingga persentase kebocoran menggambarkan pola: mereka bertambah seiring bertambahnya konten Anda sementara biaya runtime tetap tetap.

    Hasil pada Vite + Vue 3

    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

    PenyiapanStrategiUkuran Lib (gz)Ukuran Lib (min)Rata-rata JS Halaman (gz)Kebocoran lokalKebocoran halamanRata-rata Komponen (gz)Reaktivitas E2EWaktu Muat Halaman
    base (tanpa i18n)-0.0 KB0.0 KB41.3 KB0.0%-1.1 KB1.8 ms10.8 ms
    vue-i18nstatic24.3 KB83.2 KB134.9 KB50.0%90.0%196.0 KB2.8 ms13.6 ms
    @intlayer/vue-i18nstatic7.9 KB23.2 KB47.0 KB15.0%0.0%8.4 KB1.5 ms9.3 ms
    vue-intlayer (native)static3.9 KB11.1 KB57.1 KB56.8%0.0%7.7 KB4.5 ms13.8 ms
    vue-intlayer (native)dynamic3.9 KB11.1 KB59.8 KB50.0%0.0%6.5 KB4.0 ms15.8 ms
    Kolom kebocoran halaman aplikasi dasar dibiarkan kosong: tanpa library i18n, sidik jari mendeteksi string yang di-hardcode dalam chunk bersama dan angkanya tidak bermakna.

    Cara membacanya

    • 88 KB lebih sedikit per halaman, komponen yang sama. vue-i18n membawa aplikasi 41.3 KB ke 134.9 KB. Build adapter dari komponen yang sama berada di 47.0 KB, 5.7 KB di atas aplikasi dasar. Sebagian besar perbedaannya adalah 74.9 KB dari src/locales yang ditarik oleh createI18n({ messages }) ke setiap halaman dan tidak pernah dibundel adapter sebagai satu blok.
    • Ukuran runtime menyusut 3x lipat. Komponen kosong yang hanya mengimpor vue-i18n berukuran 24.3 KB gzip / 83.2 KB minified: @intlify/core-base, kompiler pesan dan runtime. Adapter berukuran 7.9 KB / 23.2 KB, sebagian besar adalah inti Intlayer ditambah permukaan API vue-i18n.
    • Komponen: 23x lebih kecil. Komponen useI18n() yang dikompilasi secara terisolasi rata-rata berukuran 196 KB, karena t terikat pada instans yang menyimpan setiap pesan dari setiap lokal. Dengan adapter, komponen yang sama rata-rata berukuran 8.4 KB: komponen ini hanya mencapai kamusnya sendiri.
    • Kebocoran. vue-i18n mengirimkan setiap lokal dan string setiap halaman di setiap halaman: kebocoran lokal 50% (pada dua lokal yang diuji; dengan sepuluh lokal yang dibundel, pemborosan sebenarnya lebih tinggi), kebocoran halaman 90%. Adapter menurunkan kebocoran halaman menjadi 0% karena setiap komponen hanya mengimpor kamusnya. Kebocoran lokal berada di 15% dalam pengujian static ini; importMode: 'dynamic' adalah pengaturan yang menghilangkannya, dan konfigurasi tersebut bukan bagian dari pengujian Vue ini.
    • Reaktivitas dan waktu muat halaman. Perpindahan lokal murah untuk keduanya (1.5-2.8 ms); sistem reaktivitas Vue membuatnya demikian setelah pesan berada dalam memori. Pemuatan halaman beralih dari 13.6 ms menjadi 9.3 ms, sejalan dengan berkurangnya 88 KB JavaScript yang harus di-parse.
    • Tentang baris native. vue-intlayer dalam pengujian ini membundel setiap lokal dalam mode static dan mencapai 57.1 KB dengan runtime 3.9 KB; kamus adapter yang disinkronkan membawa lebih sedikit string lokal asing, itulah sebabnya angka per halaman lebih rendah. Runtime bawaan tetap menjadi yang teringan dari ketiganya, dan model .content.ts-nya adalah tempat blok SFC <i18n> menemukan padanannya.
    Tabel lengkap, setiap pustaka dan strategi, dalam laporan benchmark Vue.

    Mengapa angka berubah

    Kompiler Intlayer mengekstrak konten dari komponen

    Tidak ada apa pun di src/components/ yang berubah, jadi keuntungan berasal dari apa yang terikat pada useI18n.

    Dengan vue-i18n, pengikatannya adalah instans global. createI18n({ messages: { en, fr, ... } }) adalah satu impor yang menampung semuanya; setiap komponen yang memanggil useI18n() dapat mengakses semuanya, sehingga bundler tidak dapat memecahnya di bawah tingkat instans. Mengoptimalkan berarti Anda memecah en.json berdasarkan rute, memanggil setLocaleMessage() dalam guard router, dan menjaga peta rute-ke-berkas tetap benar saat komponen dipindahkan. Pemborosan tumbuh pada dua sumbu sekaligus, halaman dan lokal:

    Kebocoran konten teoretis berdasarkan arsitektur

    bash
    .
    ├── locales
    │   ├── en.json                    # string setiap halaman
    │   └── fr.json
    └── src
        ├── i18n.ts                    # createI18n({ messages: { en, fr, ... } })
        ├── main.ts                    # app.use(i18n)
        └── components
            └── Footer.vue             # useI18n(); t("footer.github")
    

    Dengan @intlayer/vue-i18n, pengikatannya adalah kamus. syncJSON mengubah setiap kunci tingkat atas en.json menjadi kamus; tahap pengoptimalan memberikan komponen kamus yang disebutkan kuncinya, sebagai impor yang dilacak dan dipecah bundler per halaman.

    bash
    .
    ├── intlayer.config.ts             # syncJSON({ format: "vue-i18n", source: ... })
    ├── locales
    │   ├── en.json                    # tidak berubah, tetap menjadi sumber kebenaran
    │   └── fr.json
    ├── .intlayer/                     # dihasilkan: satu kamus per kunci tingkat atas, per lokal
    └── src
        ├── i18n.ts                    # createI18n({})   ← impor messages dihapus
        ├── main.ts                    # app.use(i18n)    ← tidak berubah
        └── components
            └── Footer.vue             # useI18n(); t("footer.github")  ← tidak berubah
    

    Impor messages di i18n.ts adalah satu baris yang perlu dihapus. Itulah penghematan 88 KB.

    Migrasi dalam tiga langkah

    1. Pasang

      bash
      npx intlayer init --interactive
      

      Perintah ini mendeteksi vue-i18n, memasang intlayer, vue-intlayer, @intlayer/vue-i18n, dan @intlayer/sync-json-plugin, serta mengisi intlayer.config.ts. Tetap pasang vue-i18n: ini adalah dependensi sejawat dan menyediakan tipenya.

    2. Arahkan Intlayer ke berkas lokal Anda

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      import { syncJSON } from "@intlayer/sync-json-plugin";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
          defaultLocale: Locales.ENGLISH,
        },
        dictionary: {
          // "static" membundel setiap lokal; "dynamic" memuat yang aktif sesuai permintaan
          importMode: "dynamic",
          format: "vue-i18n",
        },
        plugins: [
          syncJSON({
            // dialek vue-i18n: {name}, {0}, "car | cars"
            format: "vue-i18n",
            source: ({ locale }) => `./locales/${locale}.json`,
            location: "locales",
          }),
        ],
      };
      
      export default config;
      

      locales/{locale}.json tetap berada di tempatnya semula. Setiap kunci tingkat atas (footer, hero...) menjadi kamus.

    3. Tambahkan plugin dan hapus impor messages

      vite.config.ts
      import { defineConfig } from "vite";
      import vue from "@vitejs/plugin-vue";
      import { vueI18nVitePlugin } from "@intlayer/vue-i18n/plugin";
      
      export default defineConfig({
        plugins: [vue(), vueI18nVitePlugin()],
      });
      
      src/i18n.ts
      import { createI18n } from "vue-i18n";
      
      // Sebelum: createI18n({ locale: "en", messages: { en, fr, es } })
      export const i18n = createI18n({ locale: "en" });
      

      vueI18nVitePlugin() membungkus vite-intlayer (pemantauan konten, kompilasi kamus, fase optimasi) dan membuat alias vue-i18n ke adapter. Menghapus impor messages adalah apa yang memangkas 88 KB; membiarkannya tetap membuat aplikasi berjalan namun mengirimkan keduanya.

    Apa yang dapat Anda hapus setelahnya

    Berkas / polaAlasan
    import en from "./locales/en.json" dan sejenisnyaDigunakan hanya sebagai fallback oleh adapter. Di sinilah 88 KB berada
    setLocaleMessage() di guard routerTidak ada operasi. Pemuatan per-rute sekarang menjadi tugas compiler
    @intlify/unplugin-vue-i18nTidak diperlukan: ini mengompilasi awal pesan dan blok SFC yang tidak dibaca adapter
    Blok SFC <i18n>Tidak dibaca; pindahkan ke JSON lokal atau ke .content.ts per komponen

    Apa yang Anda dapatkan di luar byte

    • Kunci bertipe. t("footer.github") memiliki tipe terhadap kamus footer yang dikompilasi; jalur yang salah adalah kesalahan TypeScript alih-alih kunci yang dirender sebagai teks.
    • npx intlayer test menggagalkan CI jika ada kunci yang hilang di lokal mana pun. npx intlayer fill menerjemahkan yang hilang dengan kunci penyedia Anda sendiri (OpenAI, Anthropic, Mistral, Gemini...) dan menulisnya kembali ke locales/{locale}.json.
    • Editor Visual dan CMS beroperasi pada JSON yang sama, sehingga non-pengembang dapat mengedit melalui UI dan berkas diperbarui.
    • Peralihan bertahap ke .content.ts. Setiap komponen dapat beralih dari useI18n() ke useIntlayer("footer") dengan berkas konten yang ditempatkan bersama. Kamus JSON dan .content.ts dapat hidup berdampingan dan digabungkan.

    Batasan yang perlu diketahui sebelum memulai

    Jika pesan Anda berada di dalam komponen, pesan tersebut harus dipindahkan ke berkas lokal, atau ke .content.ts, yang merupakan konsep serupa dengan tipe yang dihasilkan.

    setLocaleMessage() dan mergeLocaleMessage() memberikan peringatan dan kembali. Terjemahan yang diambil dari CMS saat runtime memerlukan CMS Intlayer, atau perintah intlayer pull / push.

    Menyimpan impor JSON di createI18n() mempertahankan 75 KB di dalam bundel. Hapus setelah intlayer test berhasil.

    7.9 KB dibandingkan 3.9 KB untuk vue-intlayer. Setelah setiap komponen beralih ke useIntlayer, hapus adaptor tersebut.

    Kapan menggunakan yang mana?

    Aplikasi Anda bergantung pada blok SFC <i18n>, alur setLocaleMessage() runtime, atau 90 KB per halaman tidak menjadi masalah bagi audiens Anda.

    Anda menggunakan vue-i18n dan menginginkan penghematan 88 KB, komponen 23x lebih kecil, 0% kebocoran halaman, kunci bertipe, dan pemeriksaan CI tanpa mengedit berkas .vue. Ini adalah titik masuk untuk basis kode vue-i18n yang sudah ada.

    Untuk proyek baru, atau setelah adaptor menyelesaikan tugasnya. Menawarkan runtime teringan (3.9 KB) dan model .content.ts per komponen yang menggantikan blok <i18n> dengan konten bertipe. Mulai dengan Intlayer dengan Vue atau dengan Nuxt.

    FAQ

    Tidak. Build benchmark hanya mengubah vite.config.ts, intlayer.config.ts, dan satu baris di src/i18n.ts, impor messages. Setiap panggilan useI18n(), $t, v-t, dan Options API tetap seperti semula.

    Karena useI18n() berhenti mengakses instans global. createI18n({ messages }) menyimpan setiap pesan dari setiap lokal, sehingga komponen yang dikompilasi secara terisolasi menarik 196 KB. Dengan adaptor, komponen hanya mengakses kamusnya sendiri: 8.4 KB.

    Dipertahankan. Konfigurasi datetimeFormats dan numberFormats yang diteruskan ke createI18n() dihormati, didukung oleh API Intl bawaan. Lihat pemformatan tanggal, waktu, dan angka.

    @intlayer/vue-i18n menargetkan Vite + Vue. Untuk @nuxtjs/i18n, gunakan adaptor kompatibilitas Nuxt i18n, dan lihat Intlayer dengan Nuxt untuk konfigurasi bawaan.

    Ya. Setiap komponen dapat beralih dari useI18n() ke useIntlayer("footer") dengan berkas konten yang ditempatkan bersama. Kamus JSON dan .content.ts dapat hidup berdampingan dan digabungkan.

    Perbandingan terkait

    Ekosistem library i18n Vue

    Seri adaptor yang sama:

    Pustaka yang dibandingkan secara langsung:

    Dokumentasi referensi:

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

    Kesimpulan

    @intlayer/vue-i18n mengubah apa yang diikat oleh useI18n(): dari instans global yang menyimpan setiap pesan dari setiap lokal ke kamus yang dikompilasi untuk komponen tersebut. Pada aplikasi Vite + Vue 3 yang sama, ini berarti 88 KB lebih sedikit per halaman, runtime 3x lebih kecil, komponen 23x lebih kecil dan 0% kebocoran halaman, hanya dengan satu file konfigurasi, satu baris plugin, dan satu impor yang dihapus. Blok SFC <i18n> dan pemuatan pesan runtime adalah dua hal yang tidak didukungnya, dan runtime vue-intlayer native tetap berukuran setengahnya.

    Semua data mentah, aplikasi pengujian, dan skrip ada di repositori Benchmark Bloom. Jalankan sendiri.

    Lihat dokumen 'Mengapa Intlayer?' untuk detail selengkapnya.

    Komentar

    Belum ada komentar. Jadilah yang pertama membagikan pemikiran Anda.

    Postingan Terkait

    Postingan Terbaru