Đặt câu hỏi và nhận tóm tắt tài liệu bằng cách tham chiếu trang này và nhà cung cấp AI bạn chọn
Nội dung của trang này đã được dịch bằng AI.
Xem phiên bản mới nhất của nội dung gốc bằng tiếng AnhNếu bạn có ý tưởng để cải thiện tài liệu này, vui lòng đóng góp bằng cách gửi pull request trên GitHub.
Liên kết GitHub tới tài liệuSao chép Markdown của tài liệu vào bộ nhớ tạm
Lingui VS Intlayer: Điểm chuẩn quốc tế hóa (i18n) trên React & Next.js
Lingui và Intlayer là hai thư viện trong bài đánh giá điểm chuẩn này dựa trên một trình biên dịch (compiler) thay vì một runtime thuần túy. Lingui trích xuất các thông điệp từ macro trong thời gian build và biên dịch các danh mục theo từng ngôn ngữ. Intlayer biên dịch các từ điển theo từng component và thực hiện tree-shake chúng theo từng ngôn ngữ. Về mặt lý thuyết, chúng phải rất gần nhau. Các con số cho thấy chúng bắt đầu phân kỳ ở đâu.
Dữ liệu được lấy từ Benchmark Bloom, một bộ công cụ mã nguồn mở xây dựng cùng một ứng dụng với mỗi thư viện và ghi lại những gì trình duyệt thực sự tải xuống và thực thi.
Tóm tắt (tl;dr): Lingui tiếp cận gần nhất với Intlayer về lượng JavaScript thô trên mỗi trang: 115-120 KB so với 118.6 KB trên TanStack Start sau khi định cấu hình tải lười (lazy loading), 148.6 KB so with 141.3 KB trên Next.js. Tuy nhiên khoảng cách xuất hiện ở các khía cạnh khác: một component Lingui được biên dịch độc lập nặng 58-153 KB so với 6-8 KB của Intlayer, quá trình hydrate mất 28-34 ms so với 11-14 ms, ngôn ngữ dự phòng nguồn làm rò rỉ 3-15% chuỗienvào các trangfrtrong mọi thiết lập tối ưu hóa, và việc đạt được thiết lập tối ưu đó đòi hỏi phải trích xuất, biên dịch và chọn thủ công các danh mục theo từng route. Intlayer đạt được điều đó mà không cần bất kỳ cấu hình nào.
Tóm lược
- Lingui - Dựa trên macro (
t`...`,<Trans>,msg), định dạng ICU MessageFormat, danh mục.po/ JSON, quy trình làm việclingui extract+lingui compile. Biên dịch ID thông điệp thành các hash ngắn, hỗ trợ tải danh mục động theo ngôn ngữ. Được thiết lập tốt, không phụ thuộc vào framework, hệ sinh thái công cụ dịch thuật mạnh mẽ xoay quanh file.po. - Intlayer - Mô hình nội dung lấy component làm trung tâm. Các từ điển
.content.tsnằm ngay cạnh component mà chúng phục vụ, trình biên dịch thời gian build thực hiện tree-shake và tải lười theo từng component và từng ngôn ngữ, các kiểu TypeScript nghiêm ngặt được tạo tự động từ nội dung của bạn, và các bản dịch còn thiếu sẽ báo lỗi ngay khi build. Tích hợp sẵn middleware, bộ hỗ trợ SEO, Visual Editor / CMS và dịch thuật với sự hỗ trợ của AI.
Mở bảng trong một cửa sổ bật lên để xem toàn bộ nội dung dữ liệu một cách rõ ràng
Huy hiệu cập nhật tự động. Ảnh chụp dữ liệu sẽ thay đổi theo thời gian.
So sánh tính năng chi tiết
Mở bảng trong một cửa sổ bật lên để xem toàn bộ nội dung dữ liệu một cách rõ ràng
| Tính năng | Intlayer (react-intlayer / next-intlayer) | Lingui (@lingui/core / @lingui/react) |
|---|---|---|
| Bản dịch đặt cạnh component | ✅ Có, file .content.ts đặt ngay cạnh từng component | ⚠️ Chuỗi nguồn inline trong JSX qua macro; bản dịch nằm trong danh mục .po tập trung |
| Tích hợp TypeScript | ✅ Kiểu dữ liệu nghiêm ngặt được tạo tự động từ nội dung | ⚠️ Macro có kiểu dữ liệu; ID thông điệp thì không, các mục danh mục bị thiếu không được phát hiện |
| Phát hiện bản dịch còn thiếu | ✅ Lỗi TypeScript + lỗi/cảnh báo tại thời gian build | ⚠️ lingui extract báo cáo thống kê; runtime sẽ dự phòng về chuỗi nguồn ban đầu |
| Nội dung phong phú (JSX / Markdown / component) | ✅ Hỗ trợ trực tiếp | ✅ <Trans> với các component lồng nhau |
| Hỗ trợ ICU | ⚠️ Đang phát triển | ✅ Có (macro plural, select, selectOrdinal) |
| Định dạng (ngày tháng, số, tiền tệ) | ✅ useNumber, useDate, ... (sử dụng Intl bên dưới) | ✅ i18n.date(), i18n.number() |
| Định tuyến bản địa hóa & middleware | ✅ Proxy/middleware tích hợp sẵn, getMultilingualUrls | ❌ Không thuộc phần lõi |
| Hỗ trợ SEO (hreflang, sitemap, robots) | ✅ Công cụ tích hợp sẵn | ❌ Thủ công |
| Server Component đồng bộ | ✅ useIntlayer từ next-intlayer/server hoạt động trong bất kỳ server component con nào | ⚠️ Cần một phiên bản I18n cho mỗi request, truyền xuống hoặc thiết lập qua setI18n |
| Tree-shaking (chỉ gửi nội dung sử dụng) | ✅ Theo từng component, từng ngôn ngữ, được tự động hóa bởi trình biên dịch | ⚠️ Theo từng ngôn ngữ qua lingui compile; theo từng route cần chia danh mục thủ công |
| Tải lười (Lazy loading) | ✅ importMode: 'dynamic' (một dòng cấu hình) | ⚠️ Sử dụng import() thủ công cho các danh mục đã biên dịch + i18n.load() / i18n.activate() |
| Dọn sạch nội dung không sử dụng | ✅ Các từ điển không còn sử dụng sẽ bị loại bỏ khi build | ✅ lingui extract --clean xóa các thông điệp lỗi thời |
| Kiểm thử bản dịch thiếu (CLI / CI) | ✅ npx intlayer content test | ⚠️ Thống kê từ lingui extract (mặc định không trả về mã thoát lỗi) |
| Quy trình build (Build pipeline) | ✅ Một plugin (@intlayer/swc / @intlayer/babel / vite-intlayer) | ⚠️ Plugin macro (Babel hoặc SWC) + các bước extract + compile |
| Dịch thuật bằng AI | ✅ Tích hợp sẵn, sử dụng khóa API nhà cung cấp của riêng bạn | ❌ Không |
| Trình chỉnh sửa trực quan / CMS | ✅ Trình chỉnh sửa trực quan miễn phí + CMS tùy chọn | ❌ Không (.po hoạt động với các hệ thống TMS bên ngoài) |
| Máy chủ MCP & Kỹ năng Agent | ✅ Có | ❌ Không |
| Hệ sinh thái / cộng đồng | ⚠️ Nhỏ hơn nhưng đang phát triển nhanh chóng | ✅ Đã được khẳng định, không phụ thuộc framework |
Bài kiểm tra điểm chuẩn
Những gì đã được đo lường
Bộ thử nghiệm Benchmark Bloom xây dựng cùng một ứng dụng với mỗi thư viện: 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 giống hệt nhau và nội dung giống hệt nhau. Các trang được đo lường bằng en và fr. Mỗi thư viện được triển khai theo tối đa bốn chiến lược tải, từ cấu hình cơ bản đến cấu hình tối ưu:
Mở bảng trong một cửa sổ bật lên để xem toàn bộ nội dung dữ liệu một cách rõ ràng
| Chiến lược | Mô tả | Đối tượng sử dụng |
|---|---|---|
| static | Danh mục đã biên dịch của mỗi ngôn ngữ được import và tải trước toàn bộ | Bản dựng thử nghiệm nhanh, mã do AI tạo |
| dynamic | Chỉ danh mục của ngôn ngữ đang hoạt động mới được import(), nhưng chứa toàn bộ trang | Đa số các dự án |
| scoped-static | Một danh mục cho mỗi route, tất cả được đóng gói sẵn từ đầu | Hiếm gặp |
| scoped-dynamic | Một danh mục cho mỗi route + import() tải lười. Chỉ trang hiện tại, ngôn ngữ hiện tại | Các ứng dụng có ngân sách hiệu năng nghiêm ngặt |
Intlayer không có 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, vì vậy các hàng static và dynamic của nó vốn dĩ đã được tối ưu hóa phạm vi.
Đối với mỗi bản build, bộ công cụ ghi lại:
- Kích thước thư viện (Lib size): kích thước gzip của một component trống chỉ import thư viện i18n. Chi phí cố định của runtime.
- JS trang (Page JS): lượng JavaScript gzip tải xuống trên mỗi trang, tính trung bình trên tất cả các trang và ngôn ngữ.
- % rò rỉ ngôn ngữ (Locale leak %): tỷ lệ chuỗi dịch được tìm thấy trong file JS tải về thuộc về ngôn ngữ mà người dùng không xem (được đo trên
envàfr, do đó 50% nghĩa là "ngôn ngữ đo lường còn lại có mặt đầy đủ"; với 10 ngôn ngữ được đóng gói, lượng lãng phí thực tế còn cao hơn nhiều). - % rò rỉ trang (Page leak %): tỷ lệ chuỗi dịch được tìm thấy trong JS tải về thuộc về trang mà người dùng không truy cập.
- Trung bình component (Component avg): kích thước gzip trung bình của mỗi component khi được biên dịch độc lập. Thể hiện dung lượng runtime và danh mục mà một component đơn lẻ kéo theo.
- Độ phản hồi E2E: thời gian thực tế giữa việc chọn một ngôn ngữ mới và khi thuộc tính
html[lang]được cập nhật trong DOM (Playwright, 5 lần lặp lại). - Hydrate (Hydration): thời lượng của giai đoạn hydrate trong React.
Các số liệu dưới đây được lấy từ lần chạy vào ngày 2026-09-12 với@lingui/react6.6.0 vàintlayer9.5.1. Ứng dụng thử nghiệm được thiết kế cố ý nhỏ gọn (vài chục chuỗi mỗi ngôn ngữ), do đó tỷ lệ phần trăm rò rỉ mô tả một khuôn mẫu: chúng sẽ tăng dần theo nội dung của bạn trong khi chi phí runtime cố định giữ nguyên.
Kết quả trên Next.js
Chọn các chỉ số 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
Mở bảng trong một cửa sổ bật lên để xem toàn bộ nội dung dữ liệu một cách rõ ràng
| Thư viện | Chiến lược | Kích thước Lib (gz) | JS trang TB (gz) | Rò rỉ ngôn ngữ | Rò rỉ trang | TB component (gz) | Độ phản hồi E2E | Hydrate |
|---|---|---|---|---|---|---|---|---|
| base (không i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
| Lingui | static | 11.9 KB | 207.4 KB | 50.0% | 90.0% | 73.3 KB | 15.3 ms | 15.2 ms |
| Lingui | dynamic | 11.9 KB | 145.4 KB | 2.8% | 89.9% | 19.9 KB | 15.7 ms | 12.7 ms |
| Lingui | scoped-static | 11.9 KB | 148.2 KB | 2.7% | 89.1% | 20.4 KB | 15.1 ms | 13.1 ms |
| Lingui | scoped-dynamic | 11.9 KB | 148.6 KB | 14.8% | 0.0% | 152.6 KB | 16.1 ms | 14.8 ms |
next-intlayer | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
next-intlayer | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
Cách đọc kết quả
- Chi phí runtime. Một component trống tiêu tốn 11.9 KB gzip với Lingui, so với 5.5 KB với Intlayer. Trên toàn bộ trang, cấu hình tốt nhất của Lingui ở mức +7.3 KB so với Intlayer (148.6 so với 141.3 KB); Intlayer chỉ ở mức +0.3 KB so với ứng dụng gốc không dùng i18n.
- Thiết lập đơn giản rất tốn kém. Việc tải trước mọi danh mục đã biên dịch dẫn đến kích thước 207.4 KB mỗi trang, tăng thêm +66 KB so với ứng dụng gốc. Một nửa số chuỗi ký tự thuộc về sai ngôn ngữ, 90% thuộc về sai trang.
- Tải động khắc phục rò rỉ ngôn ngữ chứ không khắc phục rò rỉ trang. Với một danh mục cho mỗi ngôn ngữ, rò rỉ trang vẫn ở mức ~90%: toàn bộ danh mục
frđược gửi trên mọi trang tiếng Pháp. Để đạt mức rò rỉ trang 0% cần có cấu hìnhscoped-dynamic: một danh mục riêng cho mỗi route, được trích xuất và biên dịch riêng, sau đó chọn lọc thủ công trong từng trang. - Dự phòng ngôn ngữ nguồn bị rò rỉ. Ngay cả trong các thiết lập tối ưu hóa, 3-15% chuỗi
envẫn bị đưa vào các trangfr. Macro của Lingui giữ lại thông điệp nguồn như một phương án dự phòng, do đó nó nằm trong bundle bên cạnh bản dịch. Intlayer giải quyết các dự phòng tại thời gian build và chỉ gửi đúng ngôn ngữ đang hoạt động. - Kích thước component bùng nổ trong
scoped-dynamic. Mỗi component được biên dịch riêng lẻ đạt trung bình 152.6 KB, vì danh mục của mọi route đều có thể truy cập được từ component import nó. Component tương tự sử dụnguseIntlayer()chỉ đạt trung bình 6.9 KB.
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
Mở bảng trong một cửa sổ bật lên để xem toàn bộ nội dung dữ liệu một cách rõ ràng
| Thư viện | Chiến lược | Kích thước Lib (gz) | JS trang TB (gz) | Rò rỉ ngôn ngữ | Rò rỉ trang | TB component (gz) | Độ phản hồi E2E | Hydrate |
|---|---|---|---|---|---|---|---|---|
| base (không i18n) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms | 21.6 ms |
| Lingui | static | 11.2 KB | 152.2 KB | 50.0% | 90.0% | 58.0 KB | 3.9 ms | 19.9 ms |
| Lingui | dynamic | 11.2 KB | 115.2 KB | 9.3% | 0.0% | 85.5 KB | 5.9 ms | 28.0 ms |
| Lingui | scoped-static | 11.2 KB | 120.8 KB | 4.0% | 0.0% | 147.9 KB | 7.1 ms | 33.9 ms |
| Lingui | scoped-dynamic | 11.2 KB | 120.2 KB | 8.6% | 0.0% | 83.7 KB | 42.1 ms | 32.9 ms |
intlayer | static | 5.0 KB | 125.8 KB | 50.0% | 0.0% | 8.1 KB | 3.2 ms | 11.5 ms |
intlayer | dynamic | 5.0 KB | 118.6 KB | 0.0% | 0.0% | 6.3 KB | 3.6 ms | 14.1 ms |
@intlayer/lingui (tương thích) | dynamic | 10.3 KB | 137.0 KB | 9.9% | 0.0% | 12.8 KB | 2.9 ms | 19.7 ms |
Cách đọc kết quả
- Về lượng JavaScript trên mỗi trang, Lingui nhỉnh hơn trong gang tấc.
dynamicLingui đạt mức 115.2 KB, thấp hơn 3.4 KB so với 118.6 KB của Intlayer. Các danh mục đã biên dịch của Lingui với ID băm rất gọn nhẹ, và router TanStack Start phân chia route đủ tốt để rò rỉ trang đã là 0% ngay ở hàngdynamic. - Mọi chỉ số khác ngoài kích thước trang đều nghiêng về Intlayer. Quá trình hydrate mất 28-34 ms với Lingui so với 11-14 ms với Intlayer:
i18n.load()+i18n.activate()phải chạy trên client trước khi React có thể hydrate. Các component được biên dịch riêng lẻ nặng 58-148 KB so với 6-8 KB. Rò rỉ ngôn ngữ không bao giờ đạt 0% (ở mức 4-9%) do ngôn ngữ dự phòng nguồn. - Việc chuyển đổi ngôn ngữ trong thiết lập tối ưu hóa diễn ra chậm.
scoped-dynamicLingui mất 42 ms để cập nhậthtml[lang]: danh mục route mới phải được tìm nạp, tải và kích hoạt trước khi thay đổi hiển thị. Intlayer chuyển đổi chỉ trong 3-4 ms ở cả hai chế độ. - Hàng
staticcủa Intlayer vốn đã có 0% rò rỉ trang vì chỉ các từ điển được import bởi các component trên trang mới được đóng gói. Một dòng cấu hình (importMode: 'dynamic') cũng loại bỏ luôn tình trạng rò rỉ ngôn ngữ. @intlayer/linguigiữ nguyên cú pháp macro của Lingui và phân phối từ các từ điển Intlayer. Nó chấp nhận hy sinh một phần dung lượng trang (137 KB, do runtime của macro vẫn tồn tại) để đổi lấy component nhỏ hơn (12.8 KB) và quá trình hydrate nhanh hơn Lingui gốc. Đây là một bước chuyển đổi dần, không phải đích đến cuối cùng.
Bảng đầy đủ trong báo cáo benchmark TanStack Start.
Tại sao lại có khoảng cách? Hai trình biên dịch, hai đơn vị xử lý

Cả hai thư viện đều thực hiện biên dịch. Sự khác biệt nằm ở chỗ chúng biên dịch cái gì.
Lingui biên dịch các danh mục. Macro trong mã nguồn của bạn được trích xuất vào một tệp .po cho mỗi ngôn ngữ, sau đó được biên dịch thành một module JS cho mỗi ngôn ngữ. Đơn vị xử lý là ngôn ngữ. Việc chia nhỏ hơn nữa, theo từng route hoặc theo từng component, đồng nghĩa với việc tạo nhiều danh mục, cấu hình lingui.config.ts để trích xuất từng danh mục từ các tập tin khác nhau, và tải đúng danh mục trên mỗi route. Phiên bản I18n runtime là biến toàn cục; mọi lệnh gọi useLingui() đều đăng ký component với nó.
Sao chép mã vào clipboard
Intlayer biên dịch các từ điển. Mỗi tệp .content.ts là một từ điển gắn liền với một key; trình biên dịch phân giải component nào import key nào và phát ra đúng đoạn JSON mà component đó cần, cho từng từ điển và từng ngôn ngữ. Đơn vị xử lý là component. Việc thu hẹp phạm vi theo route là kết quả tự nhiên: một trang chỉ tải từ điển của các component mà nó thực sự kết xuất.
Sao chép mã vào clipboard
Đó là lý do tại sao mẫu scoped-dynamic là kết quả build tự động của Intlayer nhưng lại là một dự án cấu hình thủ công đầy gian nan đối với Lingui. Khoảng cách nới rộng theo cả hai chiều cùng lúc: số trang và số ngôn ngữ:

Để có được các số liệu của hàngdynamic, hãy đặtdictionary.importMode: 'dynamic'trongintlayer.config.ts. Xem thêm tài liệu tối ưu hóa bundle.
Trải nghiệm lập trình viên
Cài đặt
Sao chép mã vào clipboard
Sao chép mã vào clipboard
Sau đó thêm @lingui/babel-plugin-lingui-macro (hoặc @lingui/swc-plugin) vào bundler, chạy lingui extract sau khi sửa đổi mã nguồn, chạy lingui compile trước khi build và bọc cây component trong <I18nProvider i18n={i18n}>.
Sao chép mã vào clipboard
Thêm intlayer() vào vite.config.ts (hoặc withIntlayer() vào next.config.ts) và bọc cây ứng dụng trong <IntlayerProvider>. Không cần bước trích xuất hay biên dịch riêng biệt: từ điển được xây dựng tự động khi bundler chạy.
Component
Sao chép mã vào clipboard
Văn bản tiếng Anh nằm trực tiếp trong component; văn bản tiếng Pháp nằm trong src/locales/fr/messages.po dưới dạng một ID đã được băm, sau khi chạy lingui extract. Nếu quên chạy lệnh hoặc quên compile, ứng dụng sẽ lặng lẽ quay về tiếng Anh.
Sao chép mã vào clipboard
Sao chép mã vào clipboard
Cả hai ngôn ngữ đều nằm trong cùng một tệp ngay cạnh component. Việc thiếu giá trị fr sẽ gây ra lỗi khi build, và sai key sẽ báo lỗi TypeScript ngay lập tức.
Bên ngoài các component
Metadata, loaders, các hàm server: bất kỳ nơi nào không có cây React.
Sao chép mã vào clipboard
Cần tạo phiên bản I18n mới cho mỗi lần gọi, tự tay tải đúng danh mục và dùng msg + i18n._() thay vì t. Như ghi nhận từ báo cáo điểm chuẩn, việc xác định khi nào dùng t, t` ` , i18n.t(), msg hay <Trans> không hề dễ đoán.
Sao chép mã vào clipboard
Giữ lại macro Lingui, tận dụng từ điển Intlayer
@intlayer/lingui là một adapter tương thích trực tiếp dành cho @lingui/core và @lingui/react. Các macro tiếp tục được biên dịch như trước; các lệnh gọi i18n._() trong runtime mà chúng biên dịch thành sẽ được cung cấp từ các từ điển Intlayer, với plugin đồng bộ .po giữ cho các danh mục hiện tại của bạn đóng vai trò là nguồn dữ liệu chuẩn. Các mẫu số nhiều và lựa chọn ICU hiển thị hoàn toàn tương tự.
Sao chép mã vào clipboard
Giữ @lingui/babel-plugin-lingui-macro / @lingui/swc-plugin chạy trước trình biên dịch Intlayer trong quá trình build. Xem thêm tài liệu tương thích Lingui.
Khi nào nên chọn thư viện nào?
Bạn muốn ICU MessageFormat với các macro có kiểu dữ liệu, dịch giả của bạn làm việc với tệp .po qua quy trình TMS hiện có, bạn thích viết trực tiếp chuỗi nguồn trong JSX và nhóm của bạn thoải mái quản lý quy trình trích xuất / biên dịch / chia nhỏ danh mục. JS trên mỗi trang của nó rất cạnh tranh khi đã thiết lập lazy loading.
Bạn muốn nội dung có phạm vi theo component, TypeScript chặt chẽ, báo lỗi thiếu khóa ngay khi build, tree-shaking và lazy loading không tốn công sức, component nhỏ gọn, hydrate nhanh, chuyển đổi ngôn ngữ tức thì và các công cụ biên tập tích hợp (Visual Editor, CMS, dịch thuật AI, máy chủ MCP). Đặc biệt phù hợp cho các codebase mô-đun lớn và hệ thống thiết kế.
Bạn đang dùng Lingui và muốn chuyển dần sang từ điển của Intlayer mà không cần chỉnh sửa macro. Các danh mục .po của bạn vẫn là nguồn chân lý duy nhất thông qua plugin đồng bộ hóa PO. Được đo lường cạnh nhau trong Lingui vs @intlayer/lingui.
FAQ
Bởi vì đơn vị biên dịch khác nhau. Lingui biên dịch một danh mục cho mỗi ngôn ngữ: mọi thứ dưới cấp độ đó (danh mục theo route, lazy loading, loại bỏ fallback khỏi bundle) đều cần cấu hình thủ công. Intlayer biên dịch một từ điển cho mỗi component, do đó phạm vi theo route là kết quả tự nhiên của quá trình build. Đó là lý do component Lingui khi biên dịch độc lập nặng 58-153 KB so với 6-8 KB của Intlayer.
Macro giữ lại thông điệp nguồn như một giải pháp dự phòng (fallback) lúc runtime, vì vậy chuỗi tiếng Anh được gửi kèm cùng với bản dịch. Benchmark ghi nhận 3-15% chuỗi en nằm trong các trang fr ở mọi cấu hình tối ưu. Intlayer giải quyết fallback ngay khi build và chỉ phân phối ngôn ngữ đang hoạt động.
Có, và trên TanStack Start nó thắng sít sao: 115.2 KB ở chế độ dynamic so với 118.6 KB của Intlayer. Các danh mục được biên dịch với mã ID băm rất nhỏ gọn. Nhưng chi phí phát sinh ở điểm khác: hydrate mất 28-34 ms so với 11-14 ms, và chuyển đổi ngôn ngữ mất 42 ms trong thiết lập scoped-dynamic.
Không. @intlayer/lingui giữ nguyên cách biên dịch t`...` , <Trans>, msg, plural, select và selectOrdinal; chỉ có nguồn giải quyết của i18n._() thay đổi. Tiếp tục giữ @lingui/babel-plugin-lingui-macro hoặc @lingui/swc-plugin trong bản build. Xem tài liệu tương thích Lingui.
Chúng được giữ lại cho macro và biến mất đối với nội dung riêng của Intlayer. Các từ điển .content.ts được tạo tự động khi bundler chạy mà không cần lệnh CLI riêng, và intlayer test sẽ làm dừng CI nếu thiếu khóa thay vì lặng lẽ quay lại chuỗi nguồn.
So sánh liên quan

Cùng benchmark, các thư viện khác:
Tìm hiểu thêm:
Tài liệu tham khảo:
Để hiểu các thư viện này đến từ đâu, hãy đọc lịch sử i18n trong JavaScript.
Ngôi sao GitHub
Số sao GitHub là một chỉ báo rõ nét về mức độ phổ biến, sự tin cậy của cộng đồng và sự phát triển bền vững của dự án. Mặc dù không phản ánh trực tiếp chất lượng kỹ thuật, chúng cho thấy số lượng lập trình viên nhận thấy dự án hữu ích và muốn áp dụng nó.
Hoạt động commit
Số sao thể hiện độ phổ biến. Số commit thể hiện lượng công sức đổ vào một dự án. Tại thời điểm viết bài, Intlayer có khoảng 7.500 commit, nhiều hơn phần lớn các thư viện được so sánh ở đây và gấp khoảng 5 lần next-intl hoặc next-i18next.
- lingui/js-lingui
- aymericzip/intlayer
Số commit trên nhánh mặc định, nguồn: GitHub API.
Intlayer là một monorepo, nên con số này bao gồm mọi gói framework, CLI và tài liệu. Hãy xem commit là tín hiệu về mức độ hoạt động, không phải về chất lượng.
Lượt tải npm
- @lingui/core
- intlayer
Nguồn: API lượt tải của npm registry.
Lượt tải ưu ái các giải pháp lâu đời nhất, không phải các giải pháp tốt nhất. Một thư viện ra mắt từ nhiều năm trước vẫn được cài đặt bởi mọi dự án đã chọn nó khi đó, mọi lần chạy CI và mọi gói phụ thuộc vào nó. Con số này đo sức ì nhiều hơn là một lựa chọn mới.
Các trợ lý AI khuếch đại hiệu ứng này. next-intl, i18next và vue-i18n xuất hiện khắp nơi trong mã nguồn mà chúng được huấn luyện, nên chúng đề xuất các thư viện này theo mặc định, mà không so sánh các lựa chọn khác. Mỗi đề xuất lại tăng lượt tải, và lượt tải đó thúc đẩy đề xuất tiếp theo. Hãy so sánh dựa trên benchmark thay vì số lượt tải.
Kết luận
Lingui là thư viện kết hợp runtime và compiler mạnh mẽ nhất trong bài kiểm tra này. Các danh mục đã biên dịch và băm của nó mang lại dung lượng JavaScript trên mỗi trang chỉ chênh lệch vài KB so với Intlayer, và thậm chí còn thấp hơn đôi chút trên TanStack Start. Nếu số byte trên mỗi trang là thước đo duy nhất, đây sẽ là một kết quả hòa.
Nhưng thực tế không chỉ có vậy. Trình biên dịch của Lingui dừng lại ở cấp độ ngôn ngữ; mọi thứ bên dưới (danh mục theo route, tải lười, ngăn chặn chuỗi dự phòng lọt vào bundle) đều đòi hỏi cấu hình thủ công. Bài kiểm tra cho thấy rõ cái giá của ranh giới này: component lớn hơn 10-20 lần, quá trình hydrate chậm hơn 2-3 lần, rò rỉ ngôn ngữ 3-15% không thể triệt tiêu và chuyển đổi ngôn ngữ mất 42 ms ở chế độ tối ưu. Trình biên dịch của Intlayer hoạt động ở cấp độ component, do đó các con số đó lần lượt là 6-8 KB, 11-14 ms, 0% và 3-4 ms mà không cần cấu hình thủ công.
Tất cả dữ liệu thô, ứng dụng thử nghiệm và script đều có trong kho lưu trữ Benchmark Bloom. Bạn có thể tự mình chạy thử.
Tham khảo 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.
