Tác giả:
    Ngày tạo:2026-09-13Cập nhật lần cuối:2026-09-27

    i18next VS @intlayer/i18next: Cùng API, Khác biệt Bundle

    i18next VS Intlayer

    @intlayer/i18next, @intlayer/react-i18next và @intlayer/next-i18next là các adapter tương thích. Chúng cung cấp API i18next mà mã nguồn của bạn đang sử dụng (useTranslation, t(), <Trans>, i18n.changeLanguage(), getFixedT, serverSideTranslations...) và phân phối bản dịch từ các từ điển được biên dịch bởi Intlayer. Các component không hề thay đổi. Runtime bên dưới chúng mới là phần thay đổi.

    Bài viết này đo lường sự thay thế đó trên cùng một ứng dụng Next.js, được xây dựng một lần với next-i18next và một lần với @intlayer/next-i18next. Các số liệu đến từ Benchmark Bloom. Để so sánh i18next và Intlayer dưới dạng thư viện, hãy đọc i18next vs Intlayer. Bài viết này tập trung vào những gì adapter mang lại khi bạn giữ nguyên mã nguồn của mình.

    tl;dr: Trên cùng một ứng dụng Next.js, việc thay thế next-i18next bằng @intlayer/next-i18next đã giảm lượng JavaScript trên mỗi trang từ 218.5 KB xuống 150.7 KB gzip (thiết lập cơ bản) và đánh bại thiết lập next-i18next được tối ưu hóa hoàn toàn (163.4 KB) 12.7 KB. Kích thước component trung bình giảm từ 78.5 KB xuống 9.7 KB, tỷ lệ rò rỉ chuỗi từ trang khác giảm từ ~90% xuống 0%, thời gian hydrate từ 15.6 ms xuống 11.3 ms, và runtime từ 19.7 KB xuống 9.4 KB. Không có component nào bị sửa đổi; chỉ cần chỉnh sửa duy nhất một tệp provider. Các plugin của i18next (backend, trình phát hiện ngôn ngữ) vẫn được chấp nhận nhưng không thực hiện hành động nào: không còn gì để tải hoặc phát hiện trong lúc runtime.

    @intlayer/i18next là gì

    i18next là một runtime. Lệnh i18n.init({ resources }) hoặc một plugin backend sẽ tải locales/{lng}/{ns}.json vào một instance toàn cục; useTranslation("about") đăng ký component với instance đó; t("title") tra cứu khóa tại thời điểm render. Namespace, lazy loading, danh sách namespace theo từng trang và tính an toàn kiểu dữ liệu (type safety) đều do bạn tự cấu hình và duy trì.

    Các adapter giữ nguyên API và thay thế instance:

    1. Import aliasing. Hàm createNextI18nPlugin() từ @intlayer/next-i18next/plugin (hoặc withI18next) bọc withIntlayer và thêm các alias cho Webpack / Turbopack để next-i18next, react-i18next và i18next tự động phân giải tới các gói tương ứng của @intlayer/*. Trên Vite, reactI18nextVitePlugin() từ @intlayer/react-i18next/plugin cũng thực hiện tương tự. Không có lệnh import nào bị đổi tên.
    2. JSON làm nguồn chân lý (source of truth). Plugin syncJSON đọc các tệp locales/{lng}/{ns}.json hiện có của bạn với format: "i18next" (đảm bảo {{name}}, lồng $t(), hậu tố _one / _other và ngữ cảnh được phân tích cú pháp chính xác) và ghi lại các bản dịch khi CLI hoặc CMS cập nhật chúng.
    3. Liên kết điểm gọi (call-site binding). Quá trình tối ưu hóa của Intlayer viết lại lệnh gọi useTranslation("about") thành một lời gọi nhận trực tiếp từ điển about theo ngôn ngữ đang hoạt động. Component không còn phải truy cập vào bộ lưu trữ toàn cục.
    components/About.tsx
    // Mã nguồn của bạn, không đổi
    import { useTranslation } from "react-i18next";
    
    const About = () => {
      const { t } = useTranslation("about");
      return <h1>{t("title")}</h1>;
    };
    
    Những gì trình biên dịch tạo ra (đã rút gọn)
    import _dicHash_about from "../.intlayer/dictionaries/about.mjs";
    import { useDictionary as useTranslation } from "@intlayer/react-i18next";
    
    const About = () => {
      const { t } = useTranslation(_dicHash_about);
      return <h1>{t("title")}</h1>;
    };
    

    Việc viết lại này chính là yếu tố làm thay đổi kích thước component và tỷ lệ rò rỉ trang trong bảng số liệu bên dưới.

    Những gì adapter giữ lại, bỏ qua và không thay thế

    API i18nextVới @intlayer/*
    useTranslation("ns"), useTranslation("ns", { keyPrefix })✅ Giữ lại. Được liên kết với từ điển ns tại thời điểm build; các khóa có kiểu dữ liệu theo nội dung của bạn
    t("key", { name }), {{interpolation}}, lồng $t(key)✅ Giữ lại
    Số nhiều key_one / key_other, ngữ cảnh key_male, returnObjects✅ Giữ lại. Số nhiều được đánh giá bằng Intl.PluralRules
    <Trans> với components, thẻ đánh số <1>...</1>, values✅ Giữ lại
    withTranslation, Translation, I18nContext✅ Giữ lại
    i18n.changeLanguage(), i18n.language, i18n.dir(), on("languageChanged")✅ Giữ lại. changeLanguage điều khiển locale của Intlayer
    getFixedT(lng, ns, keyPrefix), i18n.exists(), hasLoadedNamespace()✅ Giữ lại
    i18n.use(Backend).use(LanguageDetector).init({...})⚠️ use() gọi hàm init của plugin và trả về; backend và detector không cần tải hay phát hiện gì tại runtime
    init({ resources }), addResourceBundle()⚠️ resources bị bỏ qua kèm cảnh báo dev; hãy xóa các lệnh import JSON để nhận lợi ích giảm bundle
    I18nextProvider i18n={i18n}⚠️ Render một IntlayerProvider; prop i18n bị bỏ qua. Trên App Router, truyền locale (xem bên dưới)
    serverSideTranslations(locale, ["common"]) (next-i18next)⚠️ Trả về cấu trúc mong đợi và không tải gì. Giữ lại hoặc xóa đều an toàn
    appWithTranslation(App) (next-i18next)✅ Giữ lại
    next-i18next.config.js⚠️ Không đọc. Các ngôn ngữ được lấy từ intlayer.config.ts
    Lệnh useTranslation() đơn lẻ không có namespace✅ Hoạt động dựa trên từ điển translation của toàn bộ tệp (splitKeys: false)

    Kết quả đo lường (Benchmark)

    Những gì đã được đo

    Bộ kiểm thử Benchmark Bloom xây dựng cùng một ứng dụng với từng cấu hình: 10 trang (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 ngôn ngữ (en, fr, es, de, it, pt, zh, ja, ko, ru), các component và nội dung giống hệt nhau. Các trang được đo bằng en và fr.

    next-i18next được xây dựng theo bốn chiến lược tải, từ việc import JSON của tất cả ngôn ngữ vào resources (static) cho đến mỗi route một namespace và tải lười (lazy load) qua backend (scoped-dynamic). Adapter được xây dựng trên cùng các component như thiết lập cơ bản, chỉ thay đổi next.config.ts, intlayer.config.ts và tệp provider. Adapter không cần biến thể "scoped": trình biên dịch tự động giới hạn phạm vi nội dung theo từng component.

    Đối với mỗi bản build, bộ kiểm thử ghi lại:

    • Lib size: kích thước gzip của một component rỗng chỉ import thư viện i18n.
    • Page JS: lượng JavaScript gzip được tải về trên mỗi trang, tính trung bình cho tất cả các trang và ngôn ngữ.
    • Locale leak %: tỷ lệ chuỗi dịch trong JS tải về thuộc về ngôn ngữ mà người dùng không xem.
    • Page leak %: tỷ lệ chuỗi dịch trong JS tải về thuộc về trang mà người dùng không truy cập.
    • Component avg: kích thước gzip trung bình của từng component khi được biên dịch độc lập.
    • E2E reactivity: thời gian thực tế giữa việc chọn ngôn ngữ mới và khi html[lang] được cập nhật trong DOM (Playwright, 5 lần lặp).
    • Hydration: thời gian của giai đoạn hydrate trong React.
    Các số liệu dưới đây được lấy từ lượt chạy ngày 2026-09-12 với next-i18next 16.3.0 (react-i18next 17.0.13, i18next 26.4.2) và @intlayer/next-i18next 9.5.1. Ứng dụng kiểm thử được thiết kế nhỏ gọn (vài chục chuỗi mỗi ngôn ngữ), do đó tỷ lệ rò rỉ mô tả một xu hướng: chúng sẽ tăng lên cùng với nội dung của bạn trong khi chi phí runtime được giữ cố định.

    Kết quả trên Next.js

    Chọn số liệu và thư viện mà bạn quan tâm:

    Số liệu

    Tải JSON động

    Tải chậm các bản dịch trong thời gian chạy

    JSON có phạm vi (phân không gian tên)

    Không gian tên dịch trên mỗi trang

    Số liệu này là gì?

    Tổng kích thước nén gzip của gói thư viện quốc tế hóa. Nó chỉ bao gồm logic của nhà cung cấp và truy xuất nội dung sau khi tree-shaking và thu nhỏ (minification).

    Tại sao nó quan trọng?

    Kích thước thư viện nhỏ hơn giúp giảm tải trọng JavaScript ban đầu, tốc độ tải nhanh hơn.

    Xem dưới dạng

    Cấu hìnhChiến lượcLib size (gz)Page JS avg (gz)Locale leakPage leakComponent avg (gz)E2E reactivityHydration
    base (không dùng i18n)-0.0 KB141.0 KB0.0%0.0%0.9 KB13.4 ms11.8 ms
    next-i18nextstatic19.7 KB218.5 KB0.0%89.8%78.5 KB16.4 ms15.6 ms
    next-i18nextdynamic19.7 KB169.5 KB50.0%89.8%26.1 KB15.4 ms27.7 ms
    next-i18nextscoped-static19.7 KB220.1 KB0.0%89.8%78.9 KB16.4 ms14.7 ms
    next-i18nextscoped-dynamic19.7 KB163.4 KB0.0%0.0%27.1 KB15.9 ms15.1 ms
    @intlayer/next-i18nextstatic9.4 KB150.7 KB0.0%0.0%9.7 KB10.7 ms11.3 ms
    @intlayer/next-i18nextdynamic9.4 KB150.7 KB0.0%0.0%9.7 KB11.9 ms10.6 ms
    next-intlayer (gốc)static5.5 KB141.3 KB0.0%0.0%8.5 KB15.5 ms16.9 ms
    next-intlayer (gốc)dynamic5.5 KB141.3 KB0.0%0.0%6.9 KB15.3 ms15.9 ms

    Cách phân tích bảng số liệu

    • Giảm 68 KB trên mỗi trang so với thiết lập cơ bản. Cấu hình resources: { en, fr, ... } gửi mọi ngôn ngữ và mọi namespace trên từng trang: 218.5 KB. Bản build adapter cho cùng các component đó chỉ còn 150.7 KB. Nó cũng vượt qua cấu hình tốt nhất của next-i18next (163.4 KB, một namespace cho mỗi route, tải lười) khoảng 12.7 KB, bởi vì riêng runtime của i18next đã nặng 19.7 KB so với 9.4 KB.
    • Rò rỉ về 0% mà không cần chạm vào component. Mọi thiết lập next-i18next ngoại trừ cấu hình scoped hoàn toàn đều gửi đi ~90% chuỗi thuộc các trang khác. Hàng dynamic thậm chí còn tệ hơn: nó không hề giảm rò rỉ giữa các trang mà lại tăng thêm 50% rò rỉ ngôn ngữ, do backend theo ngôn ngữ vẫn kéo toàn bộ namespace translation. Adapter đạt mức 0% / 0% ngay từ mã nguồn cơ bản.
    • Component: nhỏ hơn 8 lần. Một component dùng useTranslation() được biên dịch độc lập có kích thước trung bình 78.5 KB khi nhúng resources và 26-27 KB khi dùng backend, do t gắn chặt với kho lưu trữ toàn cục. Với adapter, nó chỉ còn trung bình 9.7 KB.
    • Hydration và chuyển đổi ngôn ngữ nhanh hơn. Thời gian hydrate giảm từ 15.6 ms xuống 11.3 ms (và từ 27.7 ms ở thiết lập dynamic, nơi việc nạp backend nằm trên luồng xử lý quan trọng). Chuyển đổi ngôn ngữ rút ngắn từ 15-16 ms xuống 11-12 ms.
    • Adapter không phải là runtime gốc. next-intlayer chỉ nặng 141.3 KB, thêm vỏn vẹn +0.3 KB so với ứng dụng gốc không có i18n. Adapter mang theo toàn bộ giao diện API của i18next (cú pháp nội suy, giải quyết hậu tố số nhiều và ngữ cảnh, phân tích thẻ <Trans>) trên nền tảng lõi Intlayer: 9.4 KB và +9.4 KB mỗi trang so với bản gốc. Đây là giải pháp cầu nối, không phải đích đến cuối cùng.
    Bảng đầy đủ, từng thư viện và từng chiến lược, trong báo cáo benchmark Next.js.

    Kết quả trên TanStack Start (react-i18next)

    Với Vite và TanStack Start, benchmark so sánh react-i18next thuần với intlayer:

    Thư việnChiến lượcLib size (gz)Page JS avg (gz)Locale leakPage leakComponent avg (gz)E2E reactivityHydration
    base (không dùng i18n)-0.0 KB111.0 KB0.0%0.0%0.7 KB8.1 ms21.6 ms
    react-i18nextdynamic18.4 KB136.4 KB23.1%89.8%24.8 KB123.1 ms32.9 ms
    intlayerdynamic5.0 KB118.6 KB0.0%0.0%6.3 KB3.6 ms14.1 ms
    Bảng đầy đủ trong báo cáo benchmark TanStack Start.
    Adapter react-i18next trên Vite / TanStack Start không nằm trong đợt thử nghiệm này. Số liệu cơ sở của react-i18next trên TanStack Start có tại i18next vs Intlayer: 127-184 KB mỗi trang và mất 123-185 ms khi đổi ngôn ngữ với backend tải lười.

    Lý do các con số có sự thay đổi

    The Intlayer compiler extracts content from components

    Không có gì trong thư mục components/ thay đổi, sự cải thiện đến từ nơi mà useTranslation được liên kết.

    Với i18next, liên kết hướng tới instance toàn cục. Bất cứ thứ gì được tải vào đó (tất cả các ngôn ngữ trong static, toàn bộ namespace của ngôn ngữ đang hoạt động trong dynamic) đều có thể được truy cập từ mọi component gọi useTranslation(). Trình đóng gói không thể chia nhỏ hơn những gì instance đang nắm giữ, và runtime không thể biết trước component sẽ yêu cầu những khóa nào.

    bash
    .
    ├── next-i18next.config.js
    ├── public/locales
    │   ├── en/translation.json           # chuỗi của tất cả các trang
    │   └── fr/translation.json
    ├── i18n/i18n.ts                      # i18n.use(initReactI18next).init({ resources })
    └── components
        ├── AppProviders.tsx              # <I18nextProvider i18n={i18n}>
        └── About.tsx                     # useTranslation(); t("about.title")
    

    Bất cứ thứ gì instance chứa đều được gửi đến mọi trang, và sự lãng phí gia tăng trên hai trục, trang và ngôn ngữ:

    Theoretical content leakage by architecture

    Với @intlayer/next-i18next, liên kết hướng tới từ điển. syncJSON chuyển đổi từng tệp namespace thành một từ điển; bước tối ưu hóa sẽ cung cấp cho component đúng từ điển mà nó cần, dưới dạng một import mà trình đóng gói có thể theo dõi và chia nhỏ theo từng trang và từng ngôn ngữ.

    bash
    .
    ├── intlayer.config.ts                # syncJSON({ format: "i18next", source: ... })
    ├── public/locales
    │   ├── en/translation.json           # không đổi, vẫn là nguồn dữ liệu chính
    │   └── fr/translation.json
    ├── .intlayer/                        # được tạo tự động: một từ điển cho mỗi namespace, theo từng ngôn ngữ
    └── components
        ├── AppProviders.tsx              # <IntlayerClientProvider locale={locale}>
        └── About.tsx                     # useTranslation(); t("about.title")  ← không đổi
    

    Tệp i18n/i18n.ts và lệnh import resources trở thành mã thừa (dead code). Đó chính là nguồn gốc của 68 KB tiết kiệm được.

    Di chuyển trong 3 bước

    1. Cài đặt

      bash
      npx intlayer init --interactive
      

      Lệnh này phát hiện i18next / react-i18next / next-i18next, cài đặt intlayer, gói framework tương ứng (next-intlayer hoặc react-intlayer), adapter @intlayer/* thích hợp cùng @intlayer/sync-json-plugin, đồng thời tạo sẵn cấu hình trong intlayer.config.ts. Hãy giữ lại các gói gốc: chúng đóng vai trò là peer dependencies và cung cấp các type cần thiết.

    2. Trỏ Intlayer tới các tệp ngôn ngữ của bạn

      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: {
          importMode: "dynamic",
          format: "i18next",
        },
        plugins: [
          syncJSON({
            // Cú pháp i18next: {{name}}, $t(key), key_one / key_other, key_male
            format: "i18next",
            // Một tệp cho mỗi namespace: `useTranslation("about")` → about.json
            source: ({ locale, key }) => `./public/locales/${locale}/${key}.json`,
            location: "public/locales",
          }),
        ],
      };
      
      export default config;
      

      Nếu bạn có một tệp translation.json duy nhất cho mỗi ngôn ngữ (namespace mặc định của i18next), hãy đặt splitKeys: false để toàn bộ tệp được giữ nguyên thành một từ điển và lệnh gọi useTranslation() không đối số vẫn hoạt động bình thường.

    3. Thêm plugin

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

      Trên App Router, các client component nhận ngôn ngữ từ phân đoạn [locale]. I18nextProvider của adapter không nhận giá trị locale, do đó chỉ cần thay thế một lần duy nhất trong tệp provider của bạn:

      components/AppProviders.tsx
      "use client";
      
      import { IntlayerClientProvider } from "next-intlayer";
      import type { LocalesValues } from "intlayer";
      
      export const AppProviders = ({
        locale,
        children,
      }: {
        locale: LocalesValues;
        children: React.ReactNode;
      }) => (
        <IntlayerClientProvider locale={locale}>{children}</IntlayerClientProvider>
      );
      

      Tất cả các component bên dưới nó vẫn gọi useTranslation() như bình thường.

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

      reactI18nextVitePlugin() bọc vite-intlayer và tạo alias cho react-i18next cùng i18next. Đối với dự án không dùng React, plugin i18nextVitePlugin() từ @intlayer/i18next/plugin sẽ tạo alias cho riêng i18next.

    Những gì bạn có thể xóa sau đó

    Tệp / mẫu mãLý do
    resources: { en, fr, ... } và các lệnh import JSONBị adapter bỏ qua. Đây là nơi 68 KB dư thừa từng tồn tại
    i18next-http-backend, i18next-resources-to-backendKhông còn gì cần tải tại runtime
    i18next-browser-languagedetectorPhát hiện ngôn ngữ được xử lý bởi định tuyến Intlayer (tiền tố URL, cookie, header)
    serverSideTranslations() trong getStaticPropsTrả về cấu trúc trống; vô hại, nhưng không cần thiết
    next-i18next.config.jsKhông được đọc. Ngôn ngữ được khai báo trong intlayer.config.ts
    Danh sách ns: [...] theo từng trangTrình biên dịch tự động chọn namespace cho từng component

    Những lợi ích nhận được ngoài việc giảm dung lượng

    • Khóa có kiểm tra kiểu dữ liệu (Typed keys). useTranslation("about") được kiểm tra kiểu dựa trên từ điển about đã biên dịch; gọi t("does.not.exist") sẽ sinh lỗi TypeScript thay vì chỉ trả về một chuỗi khóa.
    • npx intlayer test sẽ báo lỗi CI nếu thiếu khóa ở bất kỳ ngôn ngữ nào. npx intlayer fill tự động dịch các khóa còn thiếu bằng khóa dịch vụ của bạn (OpenAI, Anthropic, Mistral, Gemini...) và ghi lại vào locales/{lng}/{ns}.json.
    • Trình chỉnh sửa trực quan (Visual Editor) và CMS hoạt động trực tiếp trên cùng tệp JSON, cho phép người dịch chỉnh sửa qua giao diện UI và tệp được cập nhật ngay lập tức.
    • Chuyển đổi từng bước sang .content.ts. Bất kỳ component nào cũng có thể chuyển từ useTranslation("about") sang useIntlayer("about") kèm theo tệp nội dung đặt cùng thư mục. Các từ điển JSON và .content.ts có thể cùng tồn tại song song.

    Những hạn chế cần lưu ý trước khi bắt đầu

    i18n.use(HttpBackend) chỉ gọi init của plugin và không làm gì khác. Nếu ứng dụng của bạn dựa vào việc tìm nạp bản dịch từ CMS tại runtime, luồng đó sẽ không còn nữa; hãy sử dụng Intlayer CMS hoặc các lệnh intlayer pull / push để thay thế. Việc phát hiện ngôn ngữ sẽ trở thành cấu hình định tuyến của Intlayer (tiền tố URL, cookie, tiêu đề).

    Không giống như một số adapter khác, @intlayer/i18next không sử dụng resources nội tuyến làm phương án dự phòng. Mỗi khóa phải tồn tại trong các từ điển được đồng bộ hóa, điều mà intlayer test sẽ xác minh.

    Chỉ một tệp, được hiển thị ở trên. Pages Router với appWithTranslation không cần làm gì cả.

    localePath, fallbackLng, reloadOnPrerender và các cấu hình tương tự không có tương đương; ngôn ngữ và dự phòng lấy từ intlayer.config.ts.

    9.4 KB runtime và +9.4 KB mỗi trang so với next-intlayer. Khi mọi component đã chuyển sang useIntlayer, hãy gỡ bỏ nó.

    So sánh tính năng

    Ngoài kích thước byte, đây là những gì mỗi lựa chọn mang lại:

    Tính năngi18next / react-i18next / next-i18nextAdapter @intlayer/*Intlayer native
    Các lời gọi t(), useTranslation, <Trans> của bạn✅✅ Giữ nguyên❌ Chuyển sang useIntlayer
    Kích thước runtime (gzip, Next.js)19.7 KB9.4 KB5.5 KB
    Rò rỉ trang khác khi không chia namespace thủ công~90%0%0%
    Key có kiểu⚠️ Khai báo thủ công✅ Từ các từ điển đã biên dịch✅ Tự động sinh
    Backend và plugin runtime✅ Hệ sinh thái plugin đầy đủ❌ Không hoạt động❌ Không áp dụng, dùng CMS
    Nội dung đặt cạnh component❌ JSON tập trung⚠️ JSON, .content.ts có thể cùng tồn tại✅ .content.ts cạnh mỗi component
    Bản dịch thiếu trong CI⚠️ Không tích hợp sẵn✅ npx intlayer test✅ npx intlayer test
    Dịch bằng AI❌ Không✅ npx intlayer fill✅ npx intlayer fill
    Trình soạn thảo trực quan / CMS❌ Qua nền tảng bên ngoài✅ Trên cùng JSON✅ Có
    Hệ sinh thái / cộng đồng✅ Rất lớn⚠️ Nhỏ hơn, phát triển nhanh⚠️ Nhỏ hơn, phát triển nhanh
    Kích thước runtime lấy từ lần chạy Next.js mô tả ở trên.

    Khi nào nên sử dụng giải pháp nào?

    Ứng dụng của bạn phụ thuộc vào các backend tại runtime (bản dịch được phục vụ bởi CMS tại thời điểm yêu cầu), vào hệ sinh thái plugin hoặc vào môi trường không phải React mà các adapter không hỗ trợ.

    Bạn đang dùng react-i18next / next-i18next và muốn tiết kiệm 68 KB, component nhỏ hơn 8 lần, 0% rò rỉ, khóa có định kiểu và kiểm tra CI mà không cần viết lại mã nguồn. Đây là điểm khởi đầu cho codebase i18next hiện có.

    Dành cho các dự án mới hoặc khi adapter đã hoàn thành nhiệm vụ. Nó có runtime nhẹ nhất (5.5 KB, +0.3 KB mỗi trang) và mở khóa các Server Components đồng bộ cùng các tệp .content.ts theo từng component. Bắt đầu với Intlayer với Next.js hoặc với Vite và React.

    FAQ

    Từ resources: { en, fr, ... }. Thiết lập cơ bản của next-i18next import JSON của mọi ngôn ngữ vào init(), do đó mỗi trang mang theo mọi namespace ở mọi ngôn ngữ: 218.5 KB mỗi trang. Adapter không bao giờ đóng gói khối đó; nó chỉ cung cấp cho mỗi component từ điển được yêu cầu, trong ngôn ngữ hoạt động.

    Có, với components, thẻ được đánh số <1>...</1> và values. Tương tự với {{interpolation}}, lồng $t(key), số nhiều key_one / key_other (được đánh giá bằng Intl.PluralRules), hậu tố ngữ cảnh và returnObjects.

    Đặt splitKeys: false trong plugin syncJSON. Toàn bộ tệp vẫn là một từ điển duy nhất và một lệnh gọi useTranslation() đơn giản sẽ tiếp tục phân giải theo nó.

    Không, đây là cầu nối. Adapter giữ nguyên API i18next và tốn 9.4 KB runtime; next-intlayer native chỉ tốn 5.5 KB và bổ sung các Server Components đồng bộ cùng các tệp .content.ts đặt cùng vị trí. Bạn có thể di chuyển từng component một vì các từ điển JSON và .content.ts cùng tồn tại.

    Có. locales/{lng}/{ns}.json vẫn là nguồn chân lý duy nhất: syncJSON đọc nó với cú pháp của i18next và ghi các bản dịch trở lại khi CLI hoặc CMS cập nhật.

    Các bài so sánh liên quan

    Cùng loạt adapter:

    Các thư viện được so sánh trực tiếp:

    Tài liệu tham khảo:

    Compat adapters:

    Migration guides:

    Để hiểu các thư viện này đến từ đâu, hãy đọc lịch sử i18n trong JavaScript.

    Kết luận

    i18next là runtime nặng nhất trong thử nghiệm benchmark này, và các adapter giúp loại bỏ phần lớn gánh nặng đó mà không bắt buộc bạn phải từ bỏ API quen thuộc. Trên cùng một ứng dụng Next.js, điều này giúp giảm 68 KB mỗi trang so với thiết lập cơ bản, tiết kiệm thêm 12.7 KB so với bản tối ưu thủ công tốt nhất, component nhỏ hơn 8 lần, 0% rò rỉ chuỗi và nhanh hơn 4 ms khi hydrate, chỉ bằng một tệp cấu hình, một dòng khai báo plugin và chỉnh sửa một tệp provider. Các backend và detector trở thành no-op, resources bị bỏ qua thay vì gộp chung, và runtime gốc next-intlayer thậm chí còn nhẹ hơn 9 KB nữa.

    Mọi dữ liệu thô, ứng dụng kiểm thử và mã kịch bản đều có sẵn trong kho lưu trữ Benchmark Bloom. Bạn có thể tự mình kiểm chứng.

    Tham khảo thêm tài liệu 'Tại sao chọn Intlayer?' để biết thêm chi tiết.

    Bình luận

    Chưa có bình luận nào. Hãy là người đầu tiên chia sẻ suy nghĩ của bạn.

    Bài viết liên quan

    Bài viết mới nhất