@intlayer/docs 8.9.4-canary.0 → 8.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/generated/docs.entry.cjs +20 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +20 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +1 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/benchmark/index.md +0 -3
- package/docs/ar/benchmark/nextjs.md +15 -6
- package/docs/ar/benchmark/solid.md +155 -0
- package/docs/ar/benchmark/svelte.md +148 -0
- package/docs/ar/benchmark/tanstack.md +12 -3
- package/docs/ar/benchmark/vue.md +160 -0
- package/docs/ar/configuration.md +16 -12
- package/docs/ar/dictionary/content_file.md +51 -1
- package/docs/ar/mcp_server.md +30 -17
- package/docs/ar/plugins/sync-po.md +333 -0
- package/docs/bn/configuration.md +16 -12
- package/docs/cs/configuration.md +16 -12
- package/docs/de/benchmark/index.md +0 -3
- package/docs/de/benchmark/nextjs.md +15 -6
- package/docs/de/benchmark/solid.md +155 -0
- package/docs/de/benchmark/svelte.md +148 -0
- package/docs/de/benchmark/tanstack.md +12 -3
- package/docs/de/benchmark/vue.md +160 -0
- package/docs/de/configuration.md +16 -12
- package/docs/de/dictionary/content_file.md +52 -2
- package/docs/de/mcp_server.md +29 -16
- package/docs/de/plugins/sync-po.md +332 -0
- package/docs/en/benchmark/nextjs.md +11 -2
- package/docs/en/benchmark/solid.md +22 -4
- package/docs/en/benchmark/svelte.md +17 -5
- package/docs/en/benchmark/tanstack.md +18 -3
- package/docs/en/benchmark/vue.md +17 -11
- package/docs/en/configuration.md +16 -13
- package/docs/en/dictionary/content_file.md +51 -1
- package/docs/en/mcp_server.md +31 -18
- package/docs/en/plugins/sync-po.md +333 -0
- package/docs/en-GB/benchmark/index.md +0 -3
- package/docs/en-GB/benchmark/nextjs.md +15 -6
- package/docs/en-GB/benchmark/solid.md +155 -0
- package/docs/en-GB/benchmark/svelte.md +148 -0
- package/docs/en-GB/benchmark/tanstack.md +12 -3
- package/docs/en-GB/benchmark/vue.md +160 -0
- package/docs/en-GB/configuration.md +15 -11
- package/docs/en-GB/dictionary/content_file.md +51 -1
- package/docs/en-GB/mcp_server.md +31 -18
- package/docs/en-GB/plugins/sync-po.md +333 -0
- package/docs/es/benchmark/index.md +0 -3
- package/docs/es/benchmark/nextjs.md +15 -6
- package/docs/es/benchmark/solid.md +155 -0
- package/docs/es/benchmark/svelte.md +148 -0
- package/docs/es/benchmark/tanstack.md +12 -3
- package/docs/es/benchmark/vue.md +160 -0
- package/docs/es/configuration.md +16 -12
- package/docs/es/dictionary/content_file.md +51 -1
- package/docs/es/mcp_server.md +30 -17
- package/docs/es/plugins/sync-po.md +333 -0
- package/docs/fr/benchmark/index.md +0 -3
- package/docs/fr/benchmark/nextjs.md +15 -6
- package/docs/fr/benchmark/solid.md +155 -0
- package/docs/fr/benchmark/svelte.md +148 -0
- package/docs/fr/benchmark/tanstack.md +12 -3
- package/docs/fr/benchmark/vue.md +160 -0
- package/docs/fr/configuration.md +16 -12
- package/docs/fr/dictionary/content_file.md +51 -1
- package/docs/fr/mcp_server.md +30 -17
- package/docs/fr/plugins/sync-po.md +333 -0
- package/docs/hi/benchmark/nextjs.md +15 -6
- package/docs/hi/benchmark/solid.md +155 -0
- package/docs/hi/benchmark/svelte.md +148 -0
- package/docs/hi/benchmark/tanstack.md +12 -3
- package/docs/hi/benchmark/vue.md +160 -0
- package/docs/hi/configuration.md +16 -12
- package/docs/hi/dictionary/content_file.md +51 -1
- package/docs/hi/mcp_server.md +31 -18
- package/docs/hi/plugins/sync-po.md +333 -0
- package/docs/id/benchmark/index.md +0 -3
- package/docs/id/benchmark/nextjs.md +15 -6
- package/docs/id/benchmark/solid.md +155 -0
- package/docs/id/benchmark/svelte.md +148 -0
- package/docs/id/benchmark/tanstack.md +12 -3
- package/docs/id/benchmark/vue.md +160 -0
- package/docs/id/configuration.md +16 -12
- package/docs/id/dictionary/content_file.md +51 -1
- package/docs/id/mcp_server.md +30 -17
- package/docs/id/plugins/sync-po.md +333 -0
- package/docs/it/benchmark/index.md +1 -4
- package/docs/it/benchmark/nextjs.md +15 -6
- package/docs/it/benchmark/solid.md +155 -0
- package/docs/it/benchmark/svelte.md +148 -0
- package/docs/it/benchmark/tanstack.md +12 -3
- package/docs/it/benchmark/vue.md +160 -0
- package/docs/it/configuration.md +16 -12
- package/docs/it/dictionary/content_file.md +51 -1
- package/docs/it/mcp_server.md +30 -17
- package/docs/it/plugins/sync-po.md +333 -0
- package/docs/ja/benchmark/index.md +5 -5
- package/docs/ja/benchmark/nextjs.md +15 -6
- package/docs/ja/benchmark/solid.md +155 -0
- package/docs/ja/benchmark/svelte.md +148 -0
- package/docs/ja/benchmark/tanstack.md +12 -3
- package/docs/ja/benchmark/vue.md +160 -0
- package/docs/ja/configuration.md +16 -12
- package/docs/ja/dictionary/content_file.md +50 -2
- package/docs/ja/intlayer_with_nextjs_no_locale_path.md +4 -3
- package/docs/ja/mcp_server.md +29 -16
- package/docs/ja/plugins/sync-po.md +333 -0
- package/docs/ko/benchmark/nextjs.md +15 -6
- package/docs/ko/benchmark/solid.md +155 -0
- package/docs/ko/benchmark/svelte.md +148 -0
- package/docs/ko/benchmark/tanstack.md +12 -3
- package/docs/ko/benchmark/vue.md +160 -0
- package/docs/ko/configuration.md +16 -12
- package/docs/ko/dictionary/content_file.md +51 -1
- package/docs/ko/intlayer_with_nextjs_no_locale_path.md +3 -2
- package/docs/ko/mcp_server.md +31 -18
- package/docs/ko/plugins/sync-po.md +333 -0
- package/docs/nl/configuration.md +16 -12
- package/docs/pl/benchmark/index.md +0 -3
- package/docs/pl/benchmark/nextjs.md +15 -6
- package/docs/pl/benchmark/solid.md +155 -0
- package/docs/pl/benchmark/svelte.md +148 -0
- package/docs/pl/benchmark/tanstack.md +12 -3
- package/docs/pl/benchmark/vue.md +160 -0
- package/docs/pl/configuration.md +16 -12
- package/docs/pl/dictionary/content_file.md +51 -1
- package/docs/pl/mcp_server.md +30 -17
- package/docs/pl/plugins/sync-po.md +333 -0
- package/docs/pt/benchmark/index.md +0 -3
- package/docs/pt/benchmark/nextjs.md +16 -7
- package/docs/pt/benchmark/solid.md +155 -0
- package/docs/pt/benchmark/svelte.md +148 -0
- package/docs/pt/benchmark/tanstack.md +13 -4
- package/docs/pt/benchmark/vue.md +160 -0
- package/docs/pt/configuration.md +16 -12
- package/docs/pt/dictionary/content_file.md +51 -1
- package/docs/pt/mcp_server.md +30 -17
- package/docs/pt/plugins/sync-po.md +333 -0
- package/docs/ru/benchmark/nextjs.md +15 -6
- package/docs/ru/benchmark/solid.md +155 -0
- package/docs/ru/benchmark/svelte.md +148 -0
- package/docs/ru/benchmark/tanstack.md +12 -3
- package/docs/ru/benchmark/vue.md +160 -0
- package/docs/ru/configuration.md +16 -12
- package/docs/ru/dictionary/content_file.md +52 -2
- package/docs/ru/mcp_server.md +30 -17
- package/docs/ru/plugins/sync-po.md +333 -0
- package/docs/tr/benchmark/index.md +0 -3
- package/docs/tr/benchmark/nextjs.md +15 -6
- package/docs/tr/benchmark/solid.md +155 -0
- package/docs/tr/benchmark/svelte.md +148 -0
- package/docs/tr/benchmark/tanstack.md +12 -3
- package/docs/tr/benchmark/vue.md +160 -0
- package/docs/tr/configuration.md +16 -12
- package/docs/tr/dictionary/content_file.md +51 -1
- package/docs/tr/mcp_server.md +31 -18
- package/docs/tr/plugins/sync-po.md +333 -0
- package/docs/uk/benchmark/nextjs.md +15 -6
- package/docs/uk/benchmark/solid.md +155 -0
- package/docs/uk/benchmark/svelte.md +148 -0
- package/docs/uk/benchmark/tanstack.md +12 -3
- package/docs/uk/benchmark/vue.md +160 -0
- package/docs/uk/configuration.md +16 -12
- package/docs/uk/dictionary/content_file.md +51 -1
- package/docs/uk/mcp_server.md +29 -16
- package/docs/uk/plugins/sync-po.md +333 -0
- package/docs/ur/configuration.md +16 -12
- package/docs/vi/benchmark/index.md +0 -3
- package/docs/vi/benchmark/nextjs.md +15 -6
- package/docs/vi/benchmark/solid.md +155 -0
- package/docs/vi/benchmark/svelte.md +148 -0
- package/docs/vi/benchmark/tanstack.md +12 -3
- package/docs/vi/benchmark/vue.md +160 -0
- package/docs/vi/configuration.md +16 -12
- package/docs/vi/dictionary/content_file.md +51 -1
- package/docs/vi/intlayer_with_nextjs_15.md +10 -57
- package/docs/vi/mcp_server.md +30 -17
- package/docs/vi/plugins/sync-po.md +333 -0
- package/docs/zh/benchmark/nextjs.md +15 -6
- package/docs/zh/benchmark/solid.md +155 -0
- package/docs/zh/benchmark/svelte.md +148 -0
- package/docs/zh/benchmark/tanstack.md +12 -3
- package/docs/zh/benchmark/vue.md +160 -0
- package/docs/zh/configuration.md +16 -12
- package/docs/zh/dictionary/content_file.md +51 -3
- package/docs/zh/mcp_server.md +31 -18
- package/docs/zh/plugins/sync-po.md +333 -0
- package/frequent_questions/ar/intlayerNode.md +3 -3
- package/frequent_questions/de/intlayerNode.md +3 -3
- package/frequent_questions/en/intlayerNode.md +3 -3
- package/frequent_questions/en-GB/intlayerNode.md +3 -3
- package/frequent_questions/es/intlayerNode.md +3 -3
- package/frequent_questions/fr/intlayerNode.md +3 -3
- package/frequent_questions/hi/intlayerNode.md +3 -3
- package/frequent_questions/id/intlayerNode.md +3 -3
- package/frequent_questions/it/intlayerNode.md +3 -3
- package/frequent_questions/ja/intlayerNode.md +3 -3
- package/frequent_questions/ko/intlayerNode.md +3 -3
- package/frequent_questions/pl/intlayerNode.md +3 -3
- package/frequent_questions/pt/intlayerNode.md +3 -3
- package/frequent_questions/ru/intlayerNode.md +3 -3
- package/frequent_questions/tr/intlayerNode.md +3 -3
- package/frequent_questions/uk/intlayerNode.md +3 -3
- package/frequent_questions/vi/intlayerNode.md +3 -3
- package/frequent_questions/zh/intlayerNode.md +3 -3
- package/package.json +8 -8
- package/src/generated/docs.entry.ts +20 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: Giải pháp i18n tốt nhất cho Vue năm 2026 - Báo cáo Benchmark
|
|
5
|
+
description: So sánh các thư viện quốc tế hóa (i18n) Vue như vue-i18n, fluent-vue và Intlayer. Báo cáo hiệu suất chi tiết về kích thước bundle, rò rỉ và tính phản ứng.
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- vue
|
|
11
|
+
- hiệu suất
|
|
12
|
+
- intlayer
|
|
13
|
+
slugs:
|
|
14
|
+
- doc
|
|
15
|
+
- benchmark
|
|
16
|
+
- vue
|
|
17
|
+
author: Aymeric PINEAU
|
|
18
|
+
applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-vue-template
|
|
19
|
+
history:
|
|
20
|
+
- version: 8.7.12
|
|
21
|
+
date: 2026-01-06
|
|
22
|
+
changes: "Khởi tạo benchmark"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Thư viện i18n cho Vue — Báo cáo Benchmark 2026
|
|
26
|
+
|
|
27
|
+
Trang này là báo cáo benchmark cho các giải pháp i18n trên Vue.
|
|
28
|
+
|
|
29
|
+
## Mục lục
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## Benchmark tương tác
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-vue" vertical/>
|
|
36
|
+
|
|
37
|
+
## Tham chiếu kết quả:
|
|
38
|
+
|
|
39
|
+
<iframe
|
|
40
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_vue.md"
|
|
41
|
+
width="100%"
|
|
42
|
+
height="600px"
|
|
43
|
+
style="border:none;">
|
|
44
|
+
</iframe>
|
|
45
|
+
|
|
46
|
+
> https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_vue.md
|
|
47
|
+
|
|
48
|
+
Xem toàn bộ kho lưu trữ benchmark [tại đây](https://github.com/intlayer-org/benchmark-i18n/tree/main).
|
|
49
|
+
|
|
50
|
+
## Giới thiệu
|
|
51
|
+
|
|
52
|
+
Các giải pháp quốc tế hóa là một trong những phụ thuộc nặng nhất trong một ứng dụng Vue. Rủi ro chính là việc gửi nội dung không cần thiết: bản dịch cho các trang khác và các ngôn ngữ khác trong bundle của một route duy nhất.
|
|
53
|
+
|
|
54
|
+
Khi ứng dụng của bạn phát triển, vấn đề đó có thể nhanh chóng làm bùng nổ lượng JavaScript gửi đến client và làm chậm quá trình điều hướng.
|
|
55
|
+
|
|
56
|
+
Trong thực tế, đối với các triển khai ít được tối ưu hóa nhất, một trang quốc tế hóa có thể nặng hơn gấp nhiều lần so với phiên bản không có i18n.
|
|
57
|
+
|
|
58
|
+
Tác động khác là đối với trải nghiệm nhà phát triển (DX): cách bạn khai báo nội dung, kiểu (types), tổ chức namespace, tải động và tính phản ứng khi thay đổi ngôn ngữ.
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: Giải pháp nhẹ nhất (v8.7.12) với tính năng scoping và tải động gốc.
|
|
63
|
+
- **vue-i18n**: Tiêu chuẩn ngành với hệ sinh thái phong phú, nhưng có thể trở nên nặng hơn đáng kể và khó tối ưu hóa cho code-splitting trong các ứng dụng lớn.
|
|
64
|
+
- **fluent-vue**: Tổ chức thông báo sáng tạo nhưng thiếu an toàn kiểu (type-safety) và hóa ra là một giải pháp cực kỳ nặng.
|
|
65
|
+
|
|
66
|
+
## Kiểm tra ứng dụng của bạn
|
|
67
|
+
|
|
68
|
+
Để nhanh chóng phát hiện các vấn đề rò rỉ i18n, tôi đã thiết lập một trình quét miễn phí có sẵn [tại đây](https://intlayer.org/i18n-seo-scanner).
|
|
69
|
+
|
|
70
|
+
<iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
71
|
+
|
|
72
|
+
## Vấn đề
|
|
73
|
+
|
|
74
|
+
Hai đòn bẩy là thiết yếu để hạn chế chi phí của một ứng dụng đa ngôn ngữ:
|
|
75
|
+
|
|
76
|
+
- Chia nhỏ nội dung theo trang / namespace để bạn không tải toàn bộ từ điển khi không cần thiết.
|
|
77
|
+
- Tải ngôn ngữ chính xác một cách linh hoạt, chỉ khi cần thiết.
|
|
78
|
+
|
|
79
|
+
Hiểu các hạn chế kỹ thuật của các phương pháp này:
|
|
80
|
+
|
|
81
|
+
**Tải động (Dynamic loading)**
|
|
82
|
+
|
|
83
|
+
Nếu không có tải động, hầu hết các giải pháp giữ tin nhắn trong bộ nhớ từ lần render đầu tiên, điều này làm tăng đáng kể overhead cho các ứng dụng có nhiều route và ngôn ngữ.
|
|
84
|
+
|
|
85
|
+
Với tải động, bạn chấp nhận một sự đánh đổi: ít JS ban đầu hơn, nhưng đôi khi có thêm một request khi chuyển đổi ngôn ngữ.
|
|
86
|
+
|
|
87
|
+
**Chia tách nội dung (Splitting)**
|
|
88
|
+
|
|
89
|
+
Các cú pháp được xây dựng xung quanh `const { t } = useI18n()` + `t('a.b.c')` rất tiện lợi nhưng thường khuyến khích giữ các đối tượng JSON lớn khi runtime. Mô hình đó làm cho tree-shaking trở nên khó khăn trừ khi thư viện cung cấp một chiến lược chia tách thực sự theo từng trang.
|
|
90
|
+
|
|
91
|
+
## Phương pháp nghiên cứu
|
|
92
|
+
|
|
93
|
+
Đối với benchmark này, chúng tôi đã so sánh các thư viện sau:
|
|
94
|
+
|
|
95
|
+
- `Base App` (Không có thư viện i18n)
|
|
96
|
+
- `vue-intlayer` (v8.7.12)
|
|
97
|
+
- `vue-i18n` (v11.4.0)
|
|
98
|
+
- `fluent-vue` (v3.8.2)
|
|
99
|
+
|
|
100
|
+
Framework là `Vue` với một ứng dụng đa ngôn ngữ gồm **10 trang** và **10 ngôn ngữ**.
|
|
101
|
+
|
|
102
|
+
Chúng tôi đã so sánh **bốn chiến lược tải**:
|
|
103
|
+
|
|
104
|
+
| Chiến lược | Không có namespace (toàn cục) | Có namespace (phạm vi/scoped) |
|
|
105
|
+
| :----------- | :---------------------------------------------- | :----------------------------------------------------------------- |
|
|
106
|
+
| **Tải tĩnh** | **Static**: Mọi thứ trong bộ nhớ khi khởi động. | **Scoped static**: Chia theo namespace; mọi thứ tải khi khởi động. |
|
|
107
|
+
| **Tải động** | **Dynamic**: Tải theo yêu cầu cho mỗi ngôn ngữ. | **Scoped dynamic**: Tải chi tiết theo namespace và ngôn ngữ. |
|
|
108
|
+
|
|
109
|
+
## Tóm tắt chiến lược
|
|
110
|
+
|
|
111
|
+
- **Static**: Đơn giản; không có độ trễ mạng sau lần tải đầu tiên. Nhược điểm: kích thước bundle lớn.
|
|
112
|
+
- **Dynamic**: Giảm trọng lượng ban đầu (lazy-loading). Lý tưởng khi bạn có nhiều ngôn ngữ.
|
|
113
|
+
- **Scoped static**: Giữ cho mã được tổ chức (tách biệt logic) mà không cần các request mạng bổ sung phức tạp.
|
|
114
|
+
- **Scoped dynamic**: Phương pháp tốt nhất cho _code splitting_ và hiệu suất. Giảm thiểu bộ nhớ bằng cách chỉ tải những gì chế độ xem hiện tại và ngôn ngữ đang hoạt động cần.
|
|
115
|
+
|
|
116
|
+
### Những gì tôi đã đo lường:
|
|
117
|
+
|
|
118
|
+
Tôi đã chạy cùng một ứng dụng đa ngôn ngữ trong một trình duyệt thực cho mọi stack, sau đó ghi lại những gì thực sự xuất hiện trên mạng và mất bao lâu. Kích thước được báo cáo **sau khi nén web thông thường**, vì điều đó gần với những gì mọi người thực sự tải xuống hơn là số lượng mã nguồn thô.
|
|
119
|
+
|
|
120
|
+
- **Kích thước thư viện quốc tế hóa**: Sau khi đóng gói, tree-shaking và thu gọn, kích thước của thư viện i18n là kích thước của mã provider + composable trong một component trống. Nó không bao gồm việc tải các file bản dịch. Nó trả lời cho câu hỏi thư viện "đắt" như thế nào trước khi nội dung của bạn xuất hiện.
|
|
121
|
+
|
|
122
|
+
- **JavaScript trên mỗi trang**: Đối với mỗi route benchmark, trình duyệt kéo bao nhiêu script cho lần truy cập đó, tính trung bình trên các trang trong bộ thử nghiệm (và trên các ngôn ngữ). Các trang nặng là các trang chậm.
|
|
123
|
+
|
|
124
|
+
- **Rò rỉ từ các ngôn ngữ khác (Leakage)**: Đó là nội dung của cùng một trang nhưng ở ngôn ngữ khác sẽ bị tải nhầm trong trang được kiểm tra. Nội dung này là không cần thiết và nên tránh (ví dụ: nội dung trang `/fr/about` trong bundle trang `/en/about`).
|
|
125
|
+
|
|
126
|
+
- **Rò rỉ từ các route khác**: Ý tưởng tương tự cho **các màn hình khác** trong ứng dụng: liệu văn bản của chúng có đi kèm khi bạn chỉ mở một trang hay không (ví dụ: nội dung trang `/en/about` trong bundle trang `/en/contact`). Điểm số cao gợi ý việc chia tách yếu hoặc các bundle quá rộng.
|
|
127
|
+
|
|
128
|
+
- **Kích thước bundle component trung bình**: Các phần UI phổ biến được đo **từng cái một** thay vì ẩn bên trong một con số ứng dụng khổng lồ. Nó cho thấy liệu quốc tế hóa có âm thầm làm phình to các component hàng ngày hay không. Ví dụ, nếu component của bạn render lại, nó sẽ tải tất cả dữ liệu đó từ bộ nhớ. Việc đính kèm một JSON khổng lồ vào bất kỳ component nào giống như kết nối một kho chứa lớn dữ liệu không sử dụng sẽ làm chậm hiệu suất component của bạn.
|
|
129
|
+
|
|
130
|
+
- **Tính phản ứng khi chuyển đổi ngôn ngữ**: Tôi lật ngôn ngữ bằng chính trình điều khiển của ứng dụng và tính thời gian cho đến khi trang đã chuyển đổi rõ ràng, những gì khách truy cập sẽ nhận thấy.
|
|
131
|
+
|
|
132
|
+
- **Công việc render sau khi thay đổi ngôn ngữ**: Một theo dõi hẹp hơn: giao diện đã tốn bao nhiêu nỗ lực để vẽ lại cho ngôn ngữ mới sau khi quá trình chuyển đổi bắt đầu. Hữu ích khi thời gian "cảm nhận" và chi phí framework khác nhau.
|
|
133
|
+
|
|
134
|
+
- **Thời gian tải trang ban đầu**: Từ khi điều hướng cho đến khi trình duyệt coi trang đã được tải đầy đủ cho các tình huống tôi đã thử nghiệm. Tốt để so sánh cold start.
|
|
135
|
+
|
|
136
|
+
- **Thời gian Hydration**: Thời gian client dành để biến server HTML thành giao diện tương tác. Dấu gạch ngang trong các bảng có nghĩa là triển khai đó không cung cấp con số hydration đáng tin cậy trong benchmark này.
|
|
137
|
+
|
|
138
|
+
## Kết quả chi tiết
|
|
139
|
+
|
|
140
|
+
### 1 — Các giải pháp cần tránh
|
|
141
|
+
|
|
142
|
+
> Không có giải pháp rõ ràng nào cần tránh trong hệ sinh thái Vue.
|
|
143
|
+
|
|
144
|
+
### 2 — Các giải pháp chấp nhận được
|
|
145
|
+
|
|
146
|
+
**(vue-i18n)** (`vue-i18n@11.4.0`):
|
|
147
|
+
|
|
148
|
+
- **vue-i18n** chắc chắn là thư viện i18n được sử dụng nhiều nhất cho Vue, nó có rất nhiều tính năng và một hệ sinh thái khổng lồ. Nhưng thực tế giải pháp này khá nặng. Ngay cả khi vue-i18n tích hợp lazy loading cho các tin nhắn, nó vẫn thiếu tính năng scoping. Trong trường hợp ứng dụng Vue SPA cổ điển thì không có vấn đề gì, nhưng đối với ứng dụng Nuxt, sử dụng @nuxt/i18n, nó dẫn đến việc bao gồm tin nhắn từ tất cả các trang vào một trang duy nhất. Đối với một ứng dụng Nuxt lớn bao gồm hơn 10 trang, nó có thể trở nên thực sự rắc rối.
|
|
149
|
+
|
|
150
|
+
Package này rất nặng (~24.3kb, gấp khoảng 9 lần `vue-intlayer`).
|
|
151
|
+
|
|
152
|
+
**(fluent-vue)** (`fluent-vue@0.5.0`):
|
|
153
|
+
|
|
154
|
+
- **fluent-vue** đưa ra một nỗ lực đổi mới thông qua định dạng .ftl. Tổ chức tin nhắn tuyệt vời, dễ dàng bắt đầu hơn. Nhưng trong thực tế, việc thiếu an toàn kiểu làm tăng rủi ro lỗi và có thể nhanh chóng trở nên tốn thời gian để debug. Hơn nữa, giải pháp đó tải các tin nhắn bằng một plugin vite bắt buộc tải tất cả nội dung ở tất cả các ngôn ngữ vào mỗi trang. Ngoài ra, đây là một giải pháp cực kỳ nặng (~92.7kb, gấp khoảng 34 lần `vue-intlayer`).
|
|
155
|
+
|
|
156
|
+
### 3 — Khuyến nghị
|
|
157
|
+
|
|
158
|
+
**(Intlayer)** (`vue-intlayer@8.7.12`):
|
|
159
|
+
|
|
160
|
+
Tôi sẽ không đích thân đánh giá `vue-intlayer` vì tính khách quan, vì đó là giải pháp của chính tôi.
|
package/docs/vi/configuration.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2024-08-13
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-05-12
|
|
4
4
|
title: Cấu hình (Configuration)
|
|
5
5
|
description: Tìm hiểu cách cấu hình Intlayer cho ứng dụng của bạn. Hiểu các cài đặt và tùy chọn khác nhau có sẵn để tùy chỉnh Intlayer theo nhu cầu của bạn.
|
|
6
6
|
keywords:
|
|
@@ -14,6 +14,9 @@ slugs:
|
|
|
14
14
|
- concept
|
|
15
15
|
- configuration
|
|
16
16
|
history:
|
|
17
|
+
- version: 8.9.4
|
|
18
|
+
date: 2026-05-12
|
|
19
|
+
changes: "Thêm hỗ trợ cho nhà cung cấp LM Studio"
|
|
17
20
|
- version: 8.7.0
|
|
18
21
|
date: 2026-04-07
|
|
19
22
|
changes: "Thêm tùy chọn `minify` và `prune` vào cấu hình build"
|
|
@@ -350,7 +353,7 @@ const config: IntlayerConfig = {
|
|
|
350
353
|
ai: {
|
|
351
354
|
/**
|
|
352
355
|
* Nhà cung cấp AI được sử dụng.
|
|
353
|
-
* Tùy chọn: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai'
|
|
356
|
+
* Tùy chọn: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai', 'lmstudio'
|
|
354
357
|
* Mặc định: 'openai'
|
|
355
358
|
*/
|
|
356
359
|
provider: "openai",
|
|
@@ -916,16 +919,17 @@ Intlayer hỗ trợ đa dạng các nhà cung cấp AI để mang lại sự lin
|
|
|
916
919
|
- **Groq**
|
|
917
920
|
- **Amazon Bedrock**
|
|
918
921
|
- **Together.ai**
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
|
922
|
-
|
|
|
923
|
-
| `
|
|
924
|
-
| `
|
|
925
|
-
| `
|
|
926
|
-
| `
|
|
927
|
-
| `
|
|
928
|
-
| `
|
|
922
|
+
- **LM Studio**
|
|
923
|
+
|
|
924
|
+
| Trường | Mô tả | Kiểu dữ liệu | Mặc định | Ví dụ | Nhận xét |
|
|
925
|
+
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
926
|
+
| `provider` | Nhà cung cấp được sử dụng cho các tính năng AI của Intlayer. | `'openai'` | <br/> `'anthropic'` | <br/> `'mistral'` | <br/> `'deepseek'` | <br/> `'gemini'` | <br/> `'ollama'` | <br/> `'openrouter'` | <br/> `'alibaba'` | <br/> `'fireworks'` | <br/> `'groq'` | <br/> `'huggingface'` | <br/> `'bedrock'` | <br/> `'googleaistudio'` | <br/> `'googlevertex'` | <br/> `'togetherai'` | <br/> `'lmstudio'` | `undefined` | `'anthropic'` | Các nhà cung cấp khác nhau yêu cầu các khóa API khác nhau và có mức giá khác nhau. |
|
|
927
|
+
| `model` | Model AI được sử dụng cho các tính năng AI. | `string` | Không có | `'gpt-4o-2024-11-20'` | Các model cụ thể phụ thuộc vào nhà cung cấp. |
|
|
928
|
+
| `temperature` | Điều khiển tính ngẫu nhiên của phản hồi AI. | `number` | Không có | `0.1` | Nhiệt độ cao hơn = sáng tạo hơn và kém đáng tin cậy hơn. |
|
|
929
|
+
| `apiKey` | Khóa API của bạn cho nhà cung cấp đã chọn. | `string` | Không có | `process.env.OPENAI_API_KEY` | Phải được giữ bí mật; sử dụng biến môi trường. |
|
|
930
|
+
| `applicationContext` | Ngữ cảnh bổ sung về ứng dụng của bạn để giúp AI tạo ra các bản dịch chính xác hơn (lĩnh vực, đối tượng mục tiêu, tông điệu, thuật ngữ). | `string` | Không có | `'ngữ cảnh ứng dụng tùy chỉnh của tôi'` | Có thể được sử dụng để thêm các quy tắc (ví dụ: `"Bạn không nên dịch các URL của bạn"` ). |
|
|
931
|
+
| `baseURL` | URL cơ sở cho AI API. | `string` | Không có | `'https://api.openai.com/v1'` <br/> `'http://localhost:5000'` | Có thể trỏ tới các endpoint AI API cục bộ hoặc tùy chỉnh. |
|
|
932
|
+
| `dataSerialization` | Định dạng tuần tự hóa dữ liệu cho các tính năng AI. | `'json'` | <br/> `'toon'` | `undefined` | `'toon'` | • `'json'`: mặc định, đáng tin cậy; sử dụng nhiều token hơn.<br/>• `'toon'`: ít token hơn, kém ổn định hơn.<br/>• Chuyển ngữ cảnh cho model dưới dạng một tham số phụ (reasoning effort, v.v.). |
|
|
929
933
|
|
|
930
934
|
---
|
|
931
935
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-02-07
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-05-12
|
|
4
4
|
title: Tệp Nội Dung
|
|
5
5
|
description: Tìm hiểu cách tùy chỉnh các phần mở rộng cho các tệp khai báo nội dung của bạn. Theo dõi tài liệu này để triển khai các điều kiện một cách hiệu quả trong dự án của bạn.
|
|
6
6
|
keywords:
|
|
@@ -12,6 +12,9 @@ slugs:
|
|
|
12
12
|
- concept
|
|
13
13
|
- content
|
|
14
14
|
history:
|
|
15
|
+
- version: 8.9.0
|
|
16
|
+
date: 2026-05-12
|
|
17
|
+
changes: "Thêm loại nút nội dung `plural`"
|
|
15
18
|
- version: 8.0.0
|
|
16
19
|
date: 2026-01-28
|
|
17
20
|
changes: "Thêm kiểu nút nội dung `html`"
|
|
@@ -69,6 +72,7 @@ import { type ReactNode } from "react";
|
|
|
69
72
|
import {
|
|
70
73
|
t,
|
|
71
74
|
enu,
|
|
75
|
+
plural,
|
|
72
76
|
cond,
|
|
73
77
|
nest,
|
|
74
78
|
md,
|
|
@@ -88,6 +92,7 @@ interface Content {
|
|
|
88
92
|
};
|
|
89
93
|
multilingualContent: string;
|
|
90
94
|
quantityContent: string;
|
|
95
|
+
pluralContent: string;
|
|
91
96
|
conditionalContent: string;
|
|
92
97
|
markdownContent: never;
|
|
93
98
|
htmlContent: never;
|
|
@@ -123,6 +128,10 @@ export default {
|
|
|
123
128
|
">5": "Một vài chiếc xe",
|
|
124
129
|
">19": "Nhiều chiếc xe",
|
|
125
130
|
}),
|
|
131
|
+
pluralContent: plural({
|
|
132
|
+
one: "One car",
|
|
133
|
+
other: "{{count}} cars",
|
|
134
|
+
}),
|
|
126
135
|
conditionalContent: cond({
|
|
127
136
|
true: "Xác thực được bật",
|
|
128
137
|
false: "Xác thực bị tắt",
|
|
@@ -177,6 +186,13 @@ export default {
|
|
|
177
186
|
">5": "Một vài chiếc xe",
|
|
178
187
|
">19": "Nhiều chiếc xe",
|
|
179
188
|
},
|
|
189
|
+
"pluralContent": {
|
|
190
|
+
"nodeType": "plural",
|
|
191
|
+
"plural": {
|
|
192
|
+
"one": "One car",
|
|
193
|
+
"other": "{{count}} cars",
|
|
194
|
+
},
|
|
195
|
+
},
|
|
180
196
|
},
|
|
181
197
|
"conditionalContent": {
|
|
182
198
|
"nodeType": "condition",
|
|
@@ -224,6 +240,7 @@ Các nút nội dung là các khối xây dựng của nội dung từ điển.
|
|
|
224
240
|
- **Giá trị nguyên thủy**: chuỗi, số, boolean, null, undefined
|
|
225
241
|
- **Node kiểu**: Các loại nội dung đặc biệt như bản dịch, điều kiện, markdown, v.v.
|
|
226
242
|
- **Hàm**: Nội dung động có thể được đánh giá tại thời gian chạy [xem Function Fetching](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/function_fetching.md)
|
|
243
|
+
- **Nội dung số nhiều**: Xem Nội dung số nhiều [Xem Nội dung số nhiều](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/plural.md)
|
|
227
244
|
- **Nội dung lồng nhau**: Tham chiếu đến các từ điển khác
|
|
228
245
|
|
|
229
246
|
#### Các loại nội dung
|
|
@@ -554,6 +571,8 @@ multilingualContent: t({
|
|
|
554
571
|
});
|
|
555
572
|
```
|
|
556
573
|
|
|
574
|
+
> Xem [Nội dung dịch (`t`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/translation.md) để biết thêm thông tin.
|
|
575
|
+
|
|
557
576
|
### Nội dung điều kiện (`cond`)
|
|
558
577
|
|
|
559
578
|
Nội dung thay đổi dựa trên các điều kiện boolean:
|
|
@@ -567,6 +586,8 @@ conditionalContent: cond({
|
|
|
567
586
|
});
|
|
568
587
|
```
|
|
569
588
|
|
|
589
|
+
> Xem [Nội dung điều kiện (`cond`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/condition.md) để biết thêm thông tin.
|
|
590
|
+
|
|
570
591
|
### Nội dung liệt kê (`enu`)
|
|
571
592
|
|
|
572
593
|
Nội dung thay đổi dựa trên các giá trị liệt kê:
|
|
@@ -581,6 +602,23 @@ statusContent: enu({
|
|
|
581
602
|
});
|
|
582
603
|
```
|
|
583
604
|
|
|
605
|
+
> Xem [Nội dung liệt kê (`enu`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/enumeration.md) để biết thêm thông tin.
|
|
606
|
+
|
|
607
|
+
### Nội dung số nhiều (`plural`)
|
|
608
|
+
|
|
609
|
+
Nội dung thay đổi dựa trên các quy tắc số nhiều:
|
|
610
|
+
|
|
611
|
+
```typescript
|
|
612
|
+
import { plural } from "intlayer";
|
|
613
|
+
|
|
614
|
+
pluralContent: plural({
|
|
615
|
+
one: "One car",
|
|
616
|
+
other: "{{count}} cars",
|
|
617
|
+
});
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
> Xem [Nội dung số nhiều Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/plural.md) để biết thêm thông tin.
|
|
621
|
+
|
|
584
622
|
### Nội dung chèn (`insert`)
|
|
585
623
|
|
|
586
624
|
Nội dung có thể được chèn vào các nội dung khác:
|
|
@@ -591,6 +629,8 @@ import { insert } from "intlayer";
|
|
|
591
629
|
insertionContent: insert("Đoạn văn bản này có thể được chèn vào bất cứ đâu");
|
|
592
630
|
```
|
|
593
631
|
|
|
632
|
+
> Xem [Nội dung chèn (`insert`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/insertion.md) để biết thêm thông tin.
|
|
633
|
+
|
|
594
634
|
### Nội dung lồng nhau (`nest`)
|
|
595
635
|
|
|
596
636
|
Tham chiếu đến các từ điển khác:
|
|
@@ -601,6 +641,8 @@ import { nest } from "intlayer";
|
|
|
601
641
|
nestedContent: nest("about-page");
|
|
602
642
|
```
|
|
603
643
|
|
|
644
|
+
> Xem [Nội dung lồng nhau (`nest`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/nesting.md) để biết thêm thông tin.
|
|
645
|
+
|
|
604
646
|
### Nội dung Markdown (`md`)
|
|
605
647
|
|
|
606
648
|
Nội dung văn bản phong phú ở định dạng Markdown:
|
|
@@ -613,6 +655,8 @@ markdownContent: md(
|
|
|
613
655
|
);
|
|
614
656
|
```
|
|
615
657
|
|
|
658
|
+
> Xem [Nội dung Markdown (`md`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/markdown.md) để biết thêm thông tin.
|
|
659
|
+
|
|
616
660
|
### Nội dung HTML (`html`)
|
|
617
661
|
|
|
618
662
|
Nội dung HTML phong phú có thể sử dụng thẻ chuẩn hoặc component tùy chỉnh:
|
|
@@ -630,6 +674,8 @@ localizedHtmlContent: t({
|
|
|
630
674
|
});
|
|
631
675
|
```
|
|
632
676
|
|
|
677
|
+
> Xem [Nội dung HTML (`html`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/html.md) để biết thêm thông tin.
|
|
678
|
+
|
|
633
679
|
### Nội dung theo giới tính (`gender`)
|
|
634
680
|
|
|
635
681
|
Nội dung thay đổi dựa trên giới tính:
|
|
@@ -644,6 +690,8 @@ genderContent: gender({
|
|
|
644
690
|
});
|
|
645
691
|
```
|
|
646
692
|
|
|
693
|
+
> Xem [Nội dung theo giới tính (`gender`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/gender.md) để biết thêm thông tin.
|
|
694
|
+
|
|
647
695
|
### Nội dung tệp tin (`file`)
|
|
648
696
|
|
|
649
697
|
Tham chiếu đến các tệp tin bên ngoài:
|
|
@@ -654,6 +702,8 @@ import { file } from "intlayer";
|
|
|
654
702
|
fileContent: file("./path/to/content.txt");
|
|
655
703
|
```
|
|
656
704
|
|
|
705
|
+
> Xem [Nội dung tệp tin (`file`) Tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/file.md) để biết thêm thông tin.
|
|
706
|
+
|
|
657
707
|
## Tạo các tệp nội dung
|
|
658
708
|
|
|
659
709
|
### Cấu trúc cơ bản của tệp nội dung
|
|
@@ -234,35 +234,22 @@ export default withIntlayer(nextConfig);
|
|
|
234
234
|
>
|
|
235
235
|
> export default nextConfigWithOtherPlugins;
|
|
236
236
|
> ```
|
|
237
|
-
>
|
|
238
|
-
> ### Bước 4: Định nghĩa các tuyến đường Locale động
|
|
239
|
-
>
|
|
240
|
-
> Xóa tất cả mọi thứ trong `RootLayout` và thay thế bằng đoạn mã sau:
|
|
241
|
-
>
|
|
242
|
-
> ```tsx {3} fileName="src/app/layout.tsx" codeFormat="typescript"
|
|
243
|
-
> import type { PropsWithChildren, FC } from "react";
|
|
244
|
-
> import "./globals.css";
|
|
245
|
-
>
|
|
246
|
-
> const RootLayout: FC<PropsWithChildren> = ({ children }) => (
|
|
247
|
-
> // Bạn vẫn có thể bao bọc các children với các provider khác, như `next-themes`, `react-query`, `framer-motion`, v.v.
|
|
248
|
-
> <>{children}</>
|
|
249
|
-
> );
|
|
250
|
-
> ```
|
|
251
237
|
|
|
252
|
-
|
|
238
|
+
### Bước 4: Định nghĩa các tuyến đường Locale động
|
|
253
239
|
|
|
254
|
-
|
|
240
|
+
Xóa tất cả mọi thứ trong `RootLayout` và thay thế bằng đoạn mã sau:
|
|
255
241
|
|
|
256
|
-
```
|
|
242
|
+
```tsx {3} fileName="src/app/layout.tsx" codeFormat={["typescript", "esm"]}
|
|
243
|
+
import type { PropsWithChildren, FC } from "react";
|
|
257
244
|
import "./globals.css";
|
|
258
245
|
|
|
259
|
-
const RootLayout = ({ children }) => (
|
|
260
|
-
// Bạn vẫn có thể bao bọc children với các provider khác, như `next-themes`, `react-query`, `framer-motion`, v.v.
|
|
246
|
+
const RootLayout: FC<PropsWithChildren> = ({ children }) => (
|
|
247
|
+
// Bạn vẫn có thể bao bọc các children với các provider khác, như `next-themes`, `react-query`, `framer-motion`, v.v.
|
|
261
248
|
<>{children}</>
|
|
262
249
|
);
|
|
263
250
|
|
|
264
251
|
export default RootLayout;
|
|
265
|
-
|
|
252
|
+
```
|
|
266
253
|
|
|
267
254
|
```jsx {1,8} fileName="src/app/layout.csx" codeFormat="commonjs"
|
|
268
255
|
require("./globals.css");
|
|
@@ -282,21 +269,7 @@ module.exports = {
|
|
|
282
269
|
|
|
283
270
|
Để triển khai dynamic routing, cung cấp đường dẫn cho locale bằng cách thêm một layout mới trong thư mục `[locale]` của bạn:
|
|
284
271
|
|
|
285
|
-
|
|
286
|
-
import type { NextLayoutIntlayer } from "next-intlayer";
|
|
287
|
-
import { Inter } from "next/font/google";
|
|
288
|
-
import { getHTMLTextDir } from "intlayer";
|
|
289
|
-
|
|
290
|
-
const inter = Inter({ subsets: ["latin"] });
|
|
291
|
-
|
|
292
|
-
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
|
|
293
|
-
const { locale } = await params;
|
|
294
|
-
return (
|
|
295
|
-
> Việc giữ cho component `RootLayout` trống cho phép thiết lập các thuộc tính [`lang`](https://developer.mozilla.org/fr/docs/Web/HTML/Global_attributes/lang) và [`dir`](https://developer.mozilla.org/fr/docs/Web/HTML/Global_attributes/dir) cho thẻ `<html>`.
|
|
296
|
-
|
|
297
|
-
Để triển khai routing động, cung cấp đường dẫn cho locale bằng cách thêm một layout mới trong thư mục `[locale]` của bạn:
|
|
298
|
-
|
|
299
|
-
```tsx fileName="src/app/[locale]/layout.tsx" codeFormat="typescript"
|
|
272
|
+
```tsx fileName="src/app/[locale]/layout.tsx" codeFormat={["typescript", "esm"]}
|
|
300
273
|
import { type NextLayoutIntlayer, IntlayerClientProvider } from "next-intlayer";
|
|
301
274
|
import { Inter } from "next/font/google";
|
|
302
275
|
import { getHTMLTextDir } from "intlayer";
|
|
@@ -317,27 +290,7 @@ const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
|
|
|
317
290
|
};
|
|
318
291
|
|
|
319
292
|
export default LocaleLayout;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
> Đoạn đường dẫn `[locale]` được sử dụng để định nghĩa locale. Ví dụ: `/en-US/about` sẽ tương ứng với `en-US` và `/fr/about` sẽ tương ứng với `fr`.
|
|
323
|
-
|
|
324
|
-
const inter = Inter({ subsets: ["latin"] });
|
|
325
|
-
|
|
326
|
-
const LocaleLayout = async ({ children, params: { locale } }) => {
|
|
327
|
-
const { locale } = await params;
|
|
328
|
-
return (
|
|
329
|
-
|
|
330
|
-
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
331
|
-
<body className={inter.className}>
|
|
332
|
-
{children}
|
|
333
|
-
</body>
|
|
334
|
-
</html>
|
|
335
|
-
);
|
|
336
|
-
};
|
|
337
|
-
|
|
338
|
-
module.exports = LocaleLayout;
|
|
339
|
-
|
|
340
|
-
````
|
|
293
|
+
```
|
|
341
294
|
|
|
342
295
|
> Đoạn đường dẫn `[locale]` được sử dụng để xác định locale. Ví dụ: `/en-US/about` sẽ tham chiếu đến `en-US` và `/fr/about` sẽ tham chiếu đến `fr`.
|
|
343
296
|
|
|
@@ -353,7 +306,7 @@ const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
|
|
|
353
306
|
};
|
|
354
307
|
|
|
355
308
|
export default LocaleLayout;
|
|
356
|
-
|
|
309
|
+
```
|
|
357
310
|
|
|
358
311
|
```jsx {1} fileName="src/app/[locale]/layout.mjx" codeFormat="esm"
|
|
359
312
|
export { generateStaticParams } from "next-intlayer"; // Dòng cần chèn
|
package/docs/vi/mcp_server.md
CHANGED
|
@@ -23,7 +23,7 @@ history:
|
|
|
23
23
|
changes: "Thêm thiết lập Claude Desktop"
|
|
24
24
|
- version: 5.5.12
|
|
25
25
|
date: 2025-07-10
|
|
26
|
-
changes: "Thêm giao thức
|
|
26
|
+
changes: "Thêm giao thức Streamable HTTP và máy chủ từ xa"
|
|
27
27
|
- version: 5.5.10
|
|
28
28
|
date: 2025-06-29
|
|
29
29
|
changes: "Khởi tạo lịch sử"
|
|
@@ -51,12 +51,12 @@ Bằng cách kích hoạt Máy chủ Intlayer MCP trong IDE của bạn, bạn s
|
|
|
51
51
|
|
|
52
52
|
> Xem danh sách đầy đủ các lệnh và tùy chọn trong [tài liệu Intlayer CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/cli/index.md).
|
|
53
53
|
|
|
54
|
-
## Máy chủ cục bộ (stdio) và máy chủ từ xa (
|
|
54
|
+
## Máy chủ cục bộ (stdio) và máy chủ từ xa (Streamable HTTP)
|
|
55
55
|
|
|
56
56
|
Máy chủ MCP có thể được sử dụng theo hai cách:
|
|
57
57
|
|
|
58
58
|
- Máy chủ cục bộ (stdio)
|
|
59
|
-
- Máy chủ từ xa (
|
|
59
|
+
- Máy chủ từ xa (Streamable HTTP)
|
|
60
60
|
|
|
61
61
|
### Máy chủ cục bộ (stdio) (khuyến nghị)
|
|
62
62
|
|
|
@@ -64,7 +64,7 @@ Intlayer cung cấp một gói NPM có thể được cài đặt cục bộ tr
|
|
|
64
64
|
|
|
65
65
|
Máy chủ này là cách được khuyến nghị để sử dụng máy chủ MCP. Vì nó tích hợp tất cả các tính năng của máy chủ MCP, bao gồm cả các công cụ CLI.
|
|
66
66
|
|
|
67
|
-
### Máy chủ từ xa (
|
|
67
|
+
### Máy chủ từ xa (Streamable HTTP)
|
|
68
68
|
|
|
69
69
|
Máy chủ MCP cũng có thể được sử dụng từ xa, sử dụng phương thức truyền SSE. Máy chủ này được Intlayer lưu trữ và có sẵn tại https://mcp.intlayer.org. Máy chủ này có thể truy cập công khai, không cần xác thực, và miễn phí sử dụng.
|
|
70
70
|
|
|
@@ -97,7 +97,7 @@ bun x intlayer init mcp
|
|
|
97
97
|
Lệnh này sẽ:
|
|
98
98
|
|
|
99
99
|
1. Hỏi bạn đang sử dụng nền tảng nào (Cursor, VS Code, Claude Desktop, v.v.).
|
|
100
|
-
2. Hỏi bạn muốn sử dụng phương thức vận chuyển nào (Máy chủ cục bộ (stdio) hoặc Máy chủ từ xa (
|
|
100
|
+
2. Hỏi bạn muốn sử dụng phương thức vận chuyển nào (Máy chủ cục bộ (stdio) hoặc Máy chủ từ xa (Streamable HTTP)).
|
|
101
101
|
3. Tự động cập nhật tệp cấu hình của bạn (ví dụ: `.cursor/mcp.json`, `.vscode/mcp.json` hoặc cấu hình Claude Desktop chung).
|
|
102
102
|
|
|
103
103
|
---
|
|
@@ -107,7 +107,7 @@ Lệnh này sẽ:
|
|
|
107
107
|
1. Mở Command Palette (Ctrl+Shift+P hoặc Cmd+Shift+P).
|
|
108
108
|
2. Nhập `Intlayer: Setup AI Agent Skills`
|
|
109
109
|
3. Chọn nền tảng bạn sử dụng (ví dụ: `VSC Code`, `Cursor`, `Windsurf`, `OpenCode`, `Claude Code`, `GitHub Copilot Workspace`, v.v.).
|
|
110
|
-
4. Chọn MCP để cài đặt (stdio,
|
|
110
|
+
4. Chọn MCP để cài đặt (stdio, Streamable HTTP)
|
|
111
111
|
5. Nhấn Enter.
|
|
112
112
|
|
|
113
113
|
---
|
|
@@ -131,16 +131,16 @@ Trong thư mục gốc dự án của bạn, thêm tệp cấu hình `.cursor/mc
|
|
|
131
131
|
}
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
### Máy chủ từ xa (
|
|
134
|
+
### Máy chủ từ xa (Streamable HTTP)
|
|
135
135
|
|
|
136
|
-
Để kết nối với máy chủ Intlayer MCP từ xa sử dụng Server-Sent Events (
|
|
136
|
+
Để kết nối với máy chủ Intlayer MCP từ xa sử dụng Server-Sent Events (Streamable HTTP), bạn có thể cấu hình client MCP của mình để kết nối với dịch vụ được lưu trữ.
|
|
137
137
|
|
|
138
138
|
```json fileName=".cursor/mcp.json"
|
|
139
139
|
{
|
|
140
140
|
"mcpServers": {
|
|
141
|
-
"intlayer": {
|
|
142
|
-
"
|
|
143
|
-
"
|
|
141
|
+
"intlayer-sse": {
|
|
142
|
+
"command": "npx",
|
|
143
|
+
"args": ["-y", "mcp-remote@latest", "https://mcp.intlayer.org"]
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
}
|
|
@@ -172,16 +172,16 @@ Tạo một file `.vscode/mcp.json` trong thư mục gốc dự án của bạn:
|
|
|
172
172
|
}
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
-
### Máy chủ từ xa (
|
|
175
|
+
### Máy chủ từ xa (Streamable HTTP)
|
|
176
176
|
|
|
177
|
-
Để kết nối với máy chủ Intlayer MCP từ xa sử dụng Server-Sent Events (
|
|
177
|
+
Để kết nối với máy chủ Intlayer MCP từ xa sử dụng Server-Sent Events (Streamable HTTP), bạn có thể cấu hình client MCP của mình để kết nối với dịch vụ được lưu trữ.
|
|
178
178
|
|
|
179
179
|
```json fileName=".vscode/mcp.json"
|
|
180
180
|
{
|
|
181
181
|
"servers": {
|
|
182
|
-
"intlayer": {
|
|
183
|
-
"
|
|
184
|
-
"
|
|
182
|
+
"intlayer-sse": {
|
|
183
|
+
"command": "npx",
|
|
184
|
+
"args": ["-y", "mcp-remote@latest", "https://mcp.intlayer.org"]
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
}
|
|
@@ -191,7 +191,7 @@ Tạo một file `.vscode/mcp.json` trong thư mục gốc dự án của bạn:
|
|
|
191
191
|
|
|
192
192
|
## Cài đặt trong ChatGPT
|
|
193
193
|
|
|
194
|
-
### Máy chủ từ xa (
|
|
194
|
+
### Máy chủ từ xa (Streamable HTTP)
|
|
195
195
|
|
|
196
196
|
Theo dõi [tài liệu chính thức](https://platform.openai.com/docs/mcp#test-and-connect-your-mcp-server) để cấu hình máy chủ MCP trong ChatGPT.
|
|
197
197
|
|
|
@@ -232,6 +232,19 @@ Theo dõi [tài liệu chính thức](https://modelcontextprotocol.io/quickstart
|
|
|
232
232
|
}
|
|
233
233
|
```
|
|
234
234
|
|
|
235
|
+
### Máy chủ từ xa (Streamable HTTP)
|
|
236
|
+
|
|
237
|
+
```json fileName="claude_desktop_config.json"
|
|
238
|
+
{
|
|
239
|
+
"mcpServers": {
|
|
240
|
+
"intlayer-sse": {
|
|
241
|
+
"command": "npx",
|
|
242
|
+
"args": ["-y", "mcp-remote@latest", "https://mcp.intlayer.org"]
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
235
248
|
---
|
|
236
249
|
|
|
237
250
|
## Sử dụng MCP Server qua CLI
|