@intlayer/docs 7.3.11 → 7.3.12
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 +19 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +19 -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/intlayer_with_nuxt.md +305 -421
- package/docs/ar/intlayer_with_react_router_v7.md +33 -4
- package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +516 -0
- package/docs/ar/intlayer_with_tanstack.md +2 -12
- package/docs/ar/intlayer_with_vite+vue.md +1 -0
- package/docs/de/intlayer_with_nuxt.md +296 -394
- package/docs/de/intlayer_with_react_router_v7.md +33 -4
- package/docs/de/intlayer_with_react_router_v7_fs_routes.md +573 -0
- package/docs/de/intlayer_with_tanstack.md +1 -0
- package/docs/de/intlayer_with_vite+vue.md +1 -0
- package/docs/en/intlayer_with_nuxt.md +242 -321
- package/docs/en/intlayer_with_react_router_v7.md +24 -0
- package/docs/en/intlayer_with_react_router_v7_fs_routes.md +570 -0
- package/docs/en/intlayer_with_tanstack.md +2 -12
- package/docs/en/intlayer_with_vite+vue.md +49 -48
- package/docs/en-GB/intlayer_with_nuxt.md +262 -358
- package/docs/en-GB/intlayer_with_react_router_v7.md +33 -4
- package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +513 -0
- package/docs/en-GB/intlayer_with_tanstack.md +2 -12
- package/docs/en-GB/intlayer_with_vite+vue.md +1 -0
- package/docs/es/intlayer_with_nuxt.md +284 -375
- package/docs/es/intlayer_with_react_router_v7.md +33 -4
- package/docs/es/intlayer_with_react_router_v7_fs_routes.md +575 -0
- package/docs/es/intlayer_with_tanstack.md +1 -0
- package/docs/es/intlayer_with_vite+vue.md +1 -2
- package/docs/fr/intlayer_with_nuxt.md +288 -387
- package/docs/fr/intlayer_with_react_router_v7.md +34 -5
- package/docs/fr/intlayer_with_react_router_v7_fs_routes.md +574 -0
- package/docs/fr/intlayer_with_tanstack.md +1 -0
- package/docs/fr/intlayer_with_vite+vue.md +1 -0
- package/docs/hi/intlayer_with_nuxt.md +318 -434
- package/docs/hi/intlayer_with_react_router_v7.md +33 -4
- package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +518 -0
- package/docs/hi/intlayer_with_tanstack.md +2 -12
- package/docs/hi/intlayer_with_vite+vue.md +1 -0
- package/docs/id/intlayer_with_nuxt.md +275 -376
- package/docs/id/intlayer_with_react_router_v7.md +29 -4
- package/docs/id/intlayer_with_react_router_v7_fs_routes.md +521 -0
- package/docs/id/intlayer_with_tanstack.md +2 -12
- package/docs/id/intlayer_with_vite+vue.md +1 -0
- package/docs/it/intlayer_with_nuxt.md +312 -408
- package/docs/it/intlayer_with_react_router_v7.md +33 -4
- package/docs/it/intlayer_with_react_router_v7_fs_routes.md +574 -0
- package/docs/it/intlayer_with_tanstack.md +1 -0
- package/docs/ja/intlayer_with_nuxt.md +319 -414
- package/docs/ja/intlayer_with_react_router_v7.md +33 -4
- package/docs/ja/intlayer_with_react_router_v7_fs_routes.md +574 -0
- package/docs/ja/intlayer_with_tanstack.md +2 -12
- package/docs/ja/intlayer_with_vite+vue.md +1 -0
- package/docs/ko/intlayer_with_nuxt.md +307 -406
- package/docs/ko/intlayer_with_react_router_v7.md +33 -4
- package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +515 -0
- package/docs/ko/intlayer_with_tanstack.md +2 -12
- package/docs/ko/intlayer_with_vite+vue.md +1 -0
- package/docs/pl/intlayer_with_nuxt.md +282 -457
- package/docs/pl/intlayer_with_react_router_v7.md +32 -5
- package/docs/pl/intlayer_with_react_router_v7_fs_routes.md +615 -0
- package/docs/pl/intlayer_with_tanstack.md +2 -12
- package/docs/pl/intlayer_with_vite+vue.md +1 -0
- package/docs/pt/intlayer_with_nuxt.md +288 -403
- package/docs/pt/intlayer_with_react_router_v7.md +28 -0
- package/docs/pt/intlayer_with_tanstack.md +1 -0
- package/docs/ru/intlayer_with_nuxt.md +300 -410
- package/docs/ru/intlayer_with_react_router_v7.md +33 -4
- package/docs/ru/intlayer_with_react_router_v7_fs_routes.md +574 -0
- package/docs/ru/intlayer_with_tanstack.md +1 -0
- package/docs/ru/intlayer_with_vite+vue.md +1 -0
- package/docs/tr/intlayer_with_nuxt.md +327 -392
- package/docs/tr/intlayer_with_react_router_v7.md +33 -4
- package/docs/tr/intlayer_with_react_router_v7_fs_routes.md +572 -0
- package/docs/tr/intlayer_with_tanstack.md +2 -12
- package/docs/tr/intlayer_with_vite+vue.md +1 -0
- package/docs/vi/intlayer_with_nuxt.md +282 -399
- package/docs/vi/intlayer_with_react_router_v7.md +29 -4
- package/docs/vi/intlayer_with_react_router_v7_fs_routes.md +523 -0
- package/docs/vi/intlayer_with_tanstack.md +2 -12
- package/docs/vi/intlayer_with_vite+vue.md +1 -0
- package/docs/zh/intlayer_with_nuxt.md +311 -444
- package/docs/zh/intlayer_with_react_router_v7.md +33 -4
- package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +516 -0
- package/docs/zh/intlayer_with_tanstack.md +2 -12
- package/docs/zh/intlayer_with_vite+vue.md +1 -0
- package/package.json +6 -6
- package/src/generated/docs.entry.ts +19 -0
|
@@ -18,6 +18,7 @@ slugs:
|
|
|
18
18
|
- vite-and-react
|
|
19
19
|
- react-router-v7
|
|
20
20
|
applicationTemplate: https://github.com/aymericzip/intlayer-react-router-v7-template
|
|
21
|
+
youtubeVideo: https://www.youtube.com/watch?v=dS9L7uJeak4
|
|
21
22
|
history:
|
|
22
23
|
- version: 6.1.5
|
|
23
24
|
date: 2025-10-03
|
|
@@ -31,7 +32,7 @@ history:
|
|
|
31
32
|
|
|
32
33
|
Hướng dẫn này trình bày cách tích hợp **Intlayer** để thực hiện quốc tế hóa liền mạch trong các dự án React Router v7 với định tuyến nhận biết locale, hỗ trợ TypeScript và các thực hành phát triển hiện đại.
|
|
33
34
|
|
|
34
|
-
##
|
|
35
|
+
## Table of Contents
|
|
35
36
|
|
|
36
37
|
<TOC/>
|
|
37
38
|
|
|
@@ -85,6 +86,29 @@ pnpm add vite-intlayer --save-dev
|
|
|
85
86
|
|
|
86
87
|
### Bước 2: Cấu hình dự án của bạn
|
|
87
88
|
|
|
89
|
+
## Hướng dẫn từng bước để thiết lập Intlayer trong ứng dụng React Router v7 với các route dựa trên hệ thống tệp
|
|
90
|
+
|
|
91
|
+
<Tab defaultTab="video">
|
|
92
|
+
<TabItem label="Video" value="video">
|
|
93
|
+
|
|
94
|
+
<iframe title="How to translate your React Router v7 app using Intlayer" class="m-auto aspect-[16/9] w-full overflow-hidden rounded-lg border-0" allow="autoplay; gyroscope;" loading="lazy" width="1080" height="auto" src="https://www.youtube.com/embed/dS9L7uJeak4?autoplay=0&origin=http://intlayer.org&controls=0&rel=1"/>
|
|
95
|
+
|
|
96
|
+
</TabItem>
|
|
97
|
+
<TabItem label="Code" value="code">
|
|
98
|
+
|
|
99
|
+
<iframe
|
|
100
|
+
src="https://stackblitz.com/github/aymericzip/intlayer-react-router-v7-template?embed=1&ctl=1&file=intlayer.config.ts"
|
|
101
|
+
className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
|
|
102
|
+
title="Demo CodeSandbox - How to Internationalize your application using Intlayer"
|
|
103
|
+
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
|
104
|
+
loading="lazy"
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
</TabItem>
|
|
108
|
+
</Tab>
|
|
109
|
+
|
|
110
|
+
See [Application Template](https://github.com/aymericzip/intlayer-react-router-v7-template) on GitHub.
|
|
111
|
+
|
|
88
112
|
Tạo một file cấu hình để cấu hình các ngôn ngữ của ứng dụng của bạn:
|
|
89
113
|
|
|
90
114
|
```typescript fileName="intlayer.config.ts" codeFormat="typescript"
|
|
@@ -327,6 +351,7 @@ import {
|
|
|
327
351
|
getLocaleName,
|
|
328
352
|
getLocalizedUrl,
|
|
329
353
|
getPathWithoutLocale,
|
|
354
|
+
Locales,
|
|
330
355
|
} from "intlayer";
|
|
331
356
|
import { setLocaleInStorage, useIntlayer, useLocale } from "react-intlayer";
|
|
332
357
|
import { Link, useLocation } from "react-router";
|
|
@@ -420,13 +445,13 @@ Bạn cũng có thể sử dụng `intlayerProxy` để thêm routing phía serv
|
|
|
420
445
|
> Lưu ý rằng để sử dụng `intlayerProxy` trong môi trường production, bạn cần chuyển gói `vite-intlayer` từ `devDependencies` sang `dependencies`.
|
|
421
446
|
|
|
422
447
|
```typescript {3,7} fileName="vite.config.ts"
|
|
448
|
+
import { reactRouter } from "@react-router/dev/vite";
|
|
423
449
|
import { defineConfig } from "vite";
|
|
424
|
-
import react from "@vitejs/plugin-react-swc";
|
|
425
450
|
import { intlayer, intlayerProxy } from "vite-intlayer";
|
|
451
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
426
452
|
|
|
427
|
-
// https://vitejs.dev/config/
|
|
428
453
|
export default defineConfig({
|
|
429
|
-
plugins: [
|
|
454
|
+
plugins: [reactRouter(), tsconfigPaths(), intlayer(), intlayerProxy()],
|
|
430
455
|
});
|
|
431
456
|
```
|
|
432
457
|
|
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-09-04
|
|
3
|
+
updatedAt: 2025-10-03
|
|
4
|
+
title: Cách dịch ứng dụng React Router v7 của bạn – hướng dẫn i18n 2025
|
|
5
|
+
description: Tìm hiểu cách thêm quốc tế hóa (i18n) vào ứng dụng React Router v7 của bạn bằng Intlayer. Theo dõi hướng dẫn toàn diện này để làm cho ứng dụng của bạn đa ngôn ngữ với định tuyến nhận biết locale.
|
|
6
|
+
keywords:
|
|
7
|
+
- Quốc tế hóa
|
|
8
|
+
- Tài liệu
|
|
9
|
+
- Intlayer
|
|
10
|
+
- React Router v7
|
|
11
|
+
- React
|
|
12
|
+
- i18n
|
|
13
|
+
- TypeScript
|
|
14
|
+
- Định tuyến theo Locale
|
|
15
|
+
slugs:
|
|
16
|
+
- doc
|
|
17
|
+
- environment
|
|
18
|
+
- vite-and-react
|
|
19
|
+
- react-router-v7-fs-routes
|
|
20
|
+
applicationTemplate: https://github.com/aymericzip/intlayer-react-router-v7-template
|
|
21
|
+
youtubeVideo: https://www.youtube.com/watch?v=dS9L7uJeak4
|
|
22
|
+
history:
|
|
23
|
+
- version: 6.1.5
|
|
24
|
+
date: 2025-10-03
|
|
25
|
+
changes: Cập nhật tài liệu
|
|
26
|
+
- version: 5.8.2
|
|
27
|
+
date: 2025-09-04
|
|
28
|
+
changes: Thêm cho React Router v7
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
# Dịch trang web React Router v7 của bạn bằng Intlayer | Quốc tế hóa (i18n)
|
|
32
|
+
|
|
33
|
+
Hướng dẫn này trình bày cách tích hợp **Intlayer** để thực hiện quốc tế hóa liền mạch trong các dự án React Router v7 với định tuyến nhận biết locale, hỗ trợ TypeScript và các thực hành phát triển hiện đại.
|
|
34
|
+
|
|
35
|
+
## Table of Contents
|
|
36
|
+
|
|
37
|
+
<TOC/>
|
|
38
|
+
|
|
39
|
+
## Intlayer là gì?
|
|
40
|
+
|
|
41
|
+
**Intlayer** là một thư viện quốc tế hóa (i18n) mã nguồn mở sáng tạo, được thiết kế để đơn giản hóa việc hỗ trợ đa ngôn ngữ trong các ứng dụng web hiện đại.
|
|
42
|
+
|
|
43
|
+
Với Intlayer, bạn có thể:
|
|
44
|
+
|
|
45
|
+
- **Dễ dàng quản lý bản dịch** bằng cách sử dụng từ điển khai báo ở cấp độ component.
|
|
46
|
+
- **Định vị động metadata**, các route và nội dung.
|
|
47
|
+
- **Đảm bảo hỗ trợ TypeScript** với các kiểu được tự động tạo, cải thiện tính năng tự động hoàn thành và phát hiện lỗi.
|
|
48
|
+
- **Tận hưởng các tính năng nâng cao**, như phát hiện và chuyển đổi locale động.
|
|
49
|
+
- **Kích hoạt định tuyến nhận biết locale** với hệ thống định tuyến dựa trên cấu hình của React Router v7.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Hướng dẫn từng bước để thiết lập Intlayer trong ứng dụng React Router v7
|
|
54
|
+
|
|
55
|
+
<iframe
|
|
56
|
+
src="https://stackblitz.com/github/aymericzip/intlayer-react-router-v7-template?embed=1&ctl=1&file=intlayer.config.ts"
|
|
57
|
+
className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
|
|
58
|
+
title="Demo CodeSandbox - Cách quốc tế hóa ứng dụng của bạn sử dụng Intlayer"
|
|
59
|
+
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
|
60
|
+
loading="lazy"
|
|
61
|
+
/>
|
|
62
|
+
|
|
63
|
+
### Bước 1: Cài đặt các phụ thuộc
|
|
64
|
+
|
|
65
|
+
Cài đặt các gói cần thiết bằng trình quản lý gói bạn ưa thích:
|
|
66
|
+
|
|
67
|
+
```bash packageManager="npm"
|
|
68
|
+
npm install intlayer react-intlayer
|
|
69
|
+
npm install vite-intlayer --save-dev
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```bash packageManager="pnpm"
|
|
73
|
+
pnpm add intlayer react-intlayer
|
|
74
|
+
pnpm add vite-intlayer --save-dev
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- **intlayer**
|
|
78
|
+
|
|
79
|
+
Gói cốt lõi cung cấp các công cụ quốc tế hóa cho quản lý cấu hình, dịch thuật, [khai báo nội dung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/content_file.md), biên dịch lại, và các [lệnh CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_cli.md).
|
|
80
|
+
|
|
81
|
+
- **react-intlayer**
|
|
82
|
+
Gói tích hợp Intlayer với ứng dụng React. Nó cung cấp các context provider và hook cho việc quốc tế hóa trong React.
|
|
83
|
+
|
|
84
|
+
- **vite-intlayer**
|
|
85
|
+
Bao gồm plugin Vite để tích hợp Intlayer với [trình đóng gói Vite](https://vite.dev/guide/why.html#why-bundle-for-production), cũng như middleware để phát hiện ngôn ngữ ưu tiên của người dùng, quản lý cookie và xử lý chuyển hướng URL.
|
|
86
|
+
|
|
87
|
+
### Bước 2: Cấu hình dự án của bạn
|
|
88
|
+
|
|
89
|
+
## Hướng dẫn từng bước để thiết lập Intlayer trong ứng dụng React Router v7 với các route dựa trên hệ thống tệp
|
|
90
|
+
|
|
91
|
+
<Tab defaultTab="video">
|
|
92
|
+
<TabItem label="Video" value="video">
|
|
93
|
+
|
|
94
|
+
<iframe title="How to translate your React Router v7 (File-System Routes) app using Intlayer" class="m-auto aspect-[16/9] w-full overflow-hidden rounded-lg border-0" allow="autoplay; gyroscope;" loading="lazy" width="1080" height="auto" src="https://www.youtube.com/embed/dS9L7uJeak4?autoplay=0&origin=http://intlayer.org&controls=0&rel=1"/>
|
|
95
|
+
|
|
96
|
+
</TabItem>
|
|
97
|
+
<TabItem label="Code" value="code">
|
|
98
|
+
|
|
99
|
+
<iframe
|
|
100
|
+
src="https://stackblitz.com/github/aymericzip/intlayer-react-router-v7-template?embed=1&ctl=1&file=intlayer.config.ts"
|
|
101
|
+
className="m-auto overflow-hidden rounded-lg border-0 max-md:size-full max-md:h-[700px] md:aspect-16/9 md:w-full"
|
|
102
|
+
title="Demo CodeSandbox - How to Internationalize your application using Intlayer"
|
|
103
|
+
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
|
|
104
|
+
loading="lazy"
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
</TabItem>
|
|
108
|
+
</Tab>
|
|
109
|
+
|
|
110
|
+
See [Application Template](https://github.com/aymericzip/intlayer-react-router-v7-template) on GitHub.
|
|
111
|
+
|
|
112
|
+
Tạo một file cấu hình để cấu hình các ngôn ngữ của ứng dụng của bạn:
|
|
113
|
+
|
|
114
|
+
```typescript fileName="intlayer.config.ts" codeFormat="typescript"
|
|
115
|
+
import { type IntlayerConfig, Locales } from "intlayer";
|
|
116
|
+
|
|
117
|
+
const config: IntlayerConfig = {
|
|
118
|
+
internationalization: {
|
|
119
|
+
defaultLocale: Locales.ENGLISH,
|
|
120
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export default config;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
```javascript fileName="intlayer.config.mjs" codeFormat="esm"
|
|
128
|
+
import { Locales } from "intlayer";
|
|
129
|
+
|
|
130
|
+
/** @type {import('intlayer').IntlayerConfig} */
|
|
131
|
+
// cấu hình Intlayer
|
|
132
|
+
const config = {
|
|
133
|
+
internationalization: {
|
|
134
|
+
defaultLocale: Locales.ENGLISH, // ngôn ngữ mặc định
|
|
135
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], // các ngôn ngữ được hỗ trợ
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export default config;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```javascript fileName="intlayer.config.cjs" codeFormat="commonjs"
|
|
143
|
+
const { Locales } = require("intlayer");
|
|
144
|
+
|
|
145
|
+
/** @type {import('intlayer').IntlayerConfig} */
|
|
146
|
+
// cấu hình Intlayer
|
|
147
|
+
const config = {
|
|
148
|
+
internationalization: {
|
|
149
|
+
defaultLocale: Locales.ENGLISH, // ngôn ngữ mặc định
|
|
150
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], // các ngôn ngữ được hỗ trợ
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
module.exports = config;
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
> Thông qua tệp cấu hình này, bạn có thể thiết lập URL theo ngôn ngữ, chuyển hướng middleware, tên cookie, vị trí và phần mở rộng của các khai báo nội dung, tắt các log của Intlayer trên console, và nhiều hơn nữa. Để xem danh sách đầy đủ các tham số có sẵn, hãy tham khảo [tài liệu cấu hình](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/configuration.md).
|
|
158
|
+
|
|
159
|
+
### Bước 3: Tích hợp Intlayer vào cấu hình Vite của bạn
|
|
160
|
+
|
|
161
|
+
Thêm plugin intlayer vào cấu hình của bạn:
|
|
162
|
+
|
|
163
|
+
```typescript fileName="vite.config.ts"
|
|
164
|
+
import { reactRouter } from "@react-router/dev/vite";
|
|
165
|
+
import { defineConfig } from "vite";
|
|
166
|
+
import { intlayer } from "vite-intlayer";
|
|
167
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
168
|
+
|
|
169
|
+
export default defineConfig({
|
|
170
|
+
plugins: [reactRouter(), tsconfigPaths(), intlayer()],
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
> Plugin Vite `intlayer()` được sử dụng để tích hợp Intlayer với Vite. Nó đảm bảo việc xây dựng các tệp khai báo nội dung và giám sát chúng trong chế độ phát triển. Nó định nghĩa các biến môi trường Intlayer trong ứng dụng Vite. Ngoài ra, nó còn cung cấp các alias để tối ưu hiệu suất.
|
|
175
|
+
|
|
176
|
+
### Bước 4: Cấu hình các Route của React Router v7
|
|
177
|
+
|
|
178
|
+
Thiết lập cấu hình routing với các route nhận biết ngôn ngữ:
|
|
179
|
+
|
|
180
|
+
```typescript fileName="app/routes.ts"
|
|
181
|
+
import { layout, route, type RouteConfig } from "@react-router/dev/routes";
|
|
182
|
+
|
|
183
|
+
export default [
|
|
184
|
+
layout("routes/layout.tsx", [
|
|
185
|
+
route("/:lang?", "routes/page.tsx"), // Trang chủ có hỗ trợ đa ngôn ngữ
|
|
186
|
+
route("/:lang?/about", "routes/about/page.tsx"), // Trang about có hỗ trợ đa ngôn ngữ
|
|
187
|
+
]),
|
|
188
|
+
] satisfies RouteConfig;
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Bước 5: Tạo các Component Layout
|
|
192
|
+
|
|
193
|
+
Thiết lập root layout và các layout theo ngôn ngữ cụ thể:
|
|
194
|
+
|
|
195
|
+
#### Root Layout
|
|
196
|
+
|
|
197
|
+
```tsx fileName="app/routes/layout.tsx"
|
|
198
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
199
|
+
import { Outlet } from "react-router";
|
|
200
|
+
|
|
201
|
+
import type { Route } from "./+types/layout";
|
|
202
|
+
|
|
203
|
+
export default function RootLayout({ params }: Route.ComponentProps) {
|
|
204
|
+
const { locale } = params;
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<IntlayerProvider locale={locale}>
|
|
208
|
+
<Outlet />
|
|
209
|
+
</IntlayerProvider>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Bước 6: Khai báo Nội dung của bạn
|
|
215
|
+
|
|
216
|
+
Tạo và quản lý các khai báo nội dung để lưu trữ bản dịch:
|
|
217
|
+
|
|
218
|
+
```tsx fileName="app/routes/[lang]/page.content.ts"
|
|
219
|
+
import { t, type Dictionary } from "intlayer";
|
|
220
|
+
|
|
221
|
+
const pageContent = {
|
|
222
|
+
key: "page",
|
|
223
|
+
content: {
|
|
224
|
+
title: t({
|
|
225
|
+
en: "Welcome to React Router v7 + Intlayer",
|
|
226
|
+
es: "Bienvenido a React Router v7 + Intlayer",
|
|
227
|
+
fr: "Bienvenue sur React Router v7 + Intlayer",
|
|
228
|
+
}),
|
|
229
|
+
description: t({
|
|
230
|
+
en: "Xây dựng các ứng dụng đa ngôn ngữ một cách dễ dàng sử dụng React Router v7 và Intlayer.",
|
|
231
|
+
es: "Cree aplicaciones multilingües fácilmente usando React Router v7 y Intlayer.",
|
|
232
|
+
fr: "Créez des applications multilingues facilement avec React Router v7 et Intlayer.",
|
|
233
|
+
}),
|
|
234
|
+
aboutLink: t({
|
|
235
|
+
en: "Tìm hiểu về chúng tôi",
|
|
236
|
+
es: "Aprender Sobre Nosotros",
|
|
237
|
+
fr: "En savoir plus sur nous",
|
|
238
|
+
}),
|
|
239
|
+
homeLink: t({
|
|
240
|
+
en: "Trang chủ",
|
|
241
|
+
es: "Inicio",
|
|
242
|
+
fr: "Accueil",
|
|
243
|
+
}),
|
|
244
|
+
},
|
|
245
|
+
} satisfies Dictionary;
|
|
246
|
+
|
|
247
|
+
export default pageContent;
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
> Các khai báo nội dung của bạn có thể được định nghĩa ở bất kỳ đâu trong ứng dụng của bạn miễn là chúng được bao gồm trong thư mục `contentDir` (mặc định là `./app`). Và phải phù hợp với phần mở rộng của tệp khai báo nội dung (mặc định là `.content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}`).
|
|
251
|
+
|
|
252
|
+
> Để biết thêm chi tiết, hãy tham khảo [tài liệu khai báo nội dung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/content_file.md).
|
|
253
|
+
|
|
254
|
+
### Bước 7: Tạo các thành phần nhận biết ngôn ngữ
|
|
255
|
+
|
|
256
|
+
Tạo một thành phần `LocalizedLink` để điều hướng nhận biết ngôn ngữ:
|
|
257
|
+
|
|
258
|
+
```tsx fileName="app/components/localized-link.tsx"
|
|
259
|
+
import type { FC } from "react";
|
|
260
|
+
|
|
261
|
+
import { getLocalizedUrl, type LocalesValues } from "intlayer";
|
|
262
|
+
import { useLocale } from "react-intlayer";
|
|
263
|
+
import { Link, type LinkProps, type To } from "react-router";
|
|
264
|
+
|
|
265
|
+
const isExternalLink = (to: string) => /^(https?:)?\/\//.test(to);
|
|
266
|
+
|
|
267
|
+
export const locacalizeTo = (to: To, locale: LocalesValues): To => {
|
|
268
|
+
if (typeof to === "string") {
|
|
269
|
+
if (isExternalLink(to)) {
|
|
270
|
+
return to;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return getLocalizedUrl(to, locale);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (isExternalLink(to.pathname ?? "")) {
|
|
277
|
+
return to;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
...to,
|
|
282
|
+
pathname: getLocalizedUrl(to.pathname ?? "", locale),
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
export const LocalizedLink: FC<LinkProps> = (props) => {
|
|
287
|
+
const { locale } = useLocale();
|
|
288
|
+
|
|
289
|
+
return <Link {...props} to={locacalizeTo(props.to, locale)} />;
|
|
290
|
+
};
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Trong trường hợp bạn muốn điều hướng đến các route đã được địa phương hóa, bạn có thể sử dụng hook `useLocalizedNavigate`:
|
|
294
|
+
|
|
295
|
+
```tsx fileName="app/hooks/useLocalizedNavigate.ts"
|
|
296
|
+
import { useLocale } from "react-intlayer";
|
|
297
|
+
import { type NavigateOptions, type To, useNavigate } from "react-router";
|
|
298
|
+
|
|
299
|
+
import { locacalizeTo } from "~/components/localized-link";
|
|
300
|
+
|
|
301
|
+
export const useLocalizedNavigate = () => {
|
|
302
|
+
const navigate = useNavigate();
|
|
303
|
+
const { locale } = useLocale();
|
|
304
|
+
|
|
305
|
+
const localizedNavigate = (to: To, options?: NavigateOptions) => {
|
|
306
|
+
const localedTo = locacalizeTo(to, locale);
|
|
307
|
+
|
|
308
|
+
navigate(localedTo, options);
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
return localizedNavigate;
|
|
312
|
+
};
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Bước 8: Sử dụng Intlayer trong các Trang của Bạn
|
|
316
|
+
|
|
317
|
+
Truy cập các từ điển nội dung của bạn trong toàn bộ ứng dụng:
|
|
318
|
+
|
|
319
|
+
#### Trang Chủ Đã Được Địa Phương Hóa
|
|
320
|
+
|
|
321
|
+
```tsx fileName="app/routes/[lang]/page.tsx"
|
|
322
|
+
import { useIntlayer } from "react-intlayer";
|
|
323
|
+
import { LocalizedLink } from "~/components/localized-link";
|
|
324
|
+
|
|
325
|
+
export default function Page() {
|
|
326
|
+
const { title, description, aboutLink } = useIntlayer("page");
|
|
327
|
+
|
|
328
|
+
return (
|
|
329
|
+
<div>
|
|
330
|
+
<h1>{title}</h1>
|
|
331
|
+
<p>{description}</p>
|
|
332
|
+
<nav>
|
|
333
|
+
<LocalizedLink to="/about">{aboutLink}</LocalizedLink>
|
|
334
|
+
</nav>
|
|
335
|
+
</div>
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
> Để tìm hiểu thêm về hook `useIntlayer`, hãy tham khảo [tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/react-intlayer/useIntlayer.md).
|
|
341
|
+
|
|
342
|
+
### Bước 9: Tạo Thành Phần Chuyển Đổi Ngôn Ngữ
|
|
343
|
+
|
|
344
|
+
Tạo một thành phần cho phép người dùng thay đổi ngôn ngữ:
|
|
345
|
+
|
|
346
|
+
```tsx fileName="app/components/locale-switcher.tsx"
|
|
347
|
+
import type { FC } from "react";
|
|
348
|
+
|
|
349
|
+
import {
|
|
350
|
+
getHTMLTextDir,
|
|
351
|
+
getLocaleName,
|
|
352
|
+
getLocalizedUrl,
|
|
353
|
+
getPathWithoutLocale,
|
|
354
|
+
Locales,
|
|
355
|
+
} from "intlayer";
|
|
356
|
+
import { setLocaleInStorage, useIntlayer, useLocale } from "react-intlayer";
|
|
357
|
+
import { Link, useLocation } from "react-router";
|
|
358
|
+
|
|
359
|
+
export const LocaleSwitcher: FC = () => {
|
|
360
|
+
const { localeSwitcherLabel } = useIntlayer("locale-switcher");
|
|
361
|
+
const { pathname } = useLocation();
|
|
362
|
+
|
|
363
|
+
const { availableLocales, locale } = useLocale();
|
|
364
|
+
|
|
365
|
+
const pathWithoutLocale = getPathWithoutLocale(pathname);
|
|
366
|
+
|
|
367
|
+
return (
|
|
368
|
+
<ol>
|
|
369
|
+
{availableLocales.map((localeItem) => (
|
|
370
|
+
<li key={localeItem}>
|
|
371
|
+
<Link
|
|
372
|
+
aria-current={localeItem === locale ? "page" : undefined}
|
|
373
|
+
aria-label={`${localeSwitcherLabel.value} ${getLocaleName(localeItem)}`}
|
|
374
|
+
onClick={() => setLocale(localeItem)}
|
|
375
|
+
to={getLocalizedUrl(pathWithoutLocale, localeItem)}
|
|
376
|
+
>
|
|
377
|
+
<span>
|
|
378
|
+
{/* Ngôn ngữ - ví dụ: FR */}
|
|
379
|
+
{localeItem}
|
|
380
|
+
</span>
|
|
381
|
+
<span>
|
|
382
|
+
{/* Ngôn ngữ theo Locale riêng của nó - ví dụ: Français */}
|
|
383
|
+
{getLocaleName(localeItem, locale)}
|
|
384
|
+
</span>
|
|
385
|
+
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
|
|
386
|
+
{/* Ngôn ngữ theo Locale hiện tại - ví dụ: Francés với locale hiện tại được đặt là Locales.SPANISH */}
|
|
387
|
+
{getLocaleName(localeItem)}
|
|
388
|
+
</span>
|
|
389
|
+
<span dir="ltr" lang={Locales.ENGLISH}>
|
|
390
|
+
{/* Ngôn ngữ bằng tiếng Anh - ví dụ: French */}
|
|
391
|
+
{getLocaleName(localeItem, Locales.ENGLISH)}
|
|
392
|
+
</span>
|
|
393
|
+
</Link>
|
|
394
|
+
</li>
|
|
395
|
+
))}
|
|
396
|
+
</ol>
|
|
397
|
+
);
|
|
398
|
+
};
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
> Để tìm hiểu thêm về hook `useLocale`, tham khảo [tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/react-intlayer/useLocale.md).
|
|
402
|
+
|
|
403
|
+
### Bước 10: Thêm quản lý thuộc tính HTML (Tùy chọn)
|
|
404
|
+
|
|
405
|
+
Tạo một hook để quản lý các thuộc tính lang và dir của HTML:
|
|
406
|
+
|
|
407
|
+
```tsx fileName="app/hooks/useI18nHTMLAttributes.tsx"
|
|
408
|
+
import { getHTMLTextDir } from "intlayer";
|
|
409
|
+
import { useEffect } from "react";
|
|
410
|
+
import { useLocale } from "react-intlayer";
|
|
411
|
+
|
|
412
|
+
export const useI18nHTMLAttributes = () => {
|
|
413
|
+
const { locale } = useLocale();
|
|
414
|
+
|
|
415
|
+
useEffect(() => {
|
|
416
|
+
document.documentElement.lang = locale; // đặt thuộc tính lang của thẻ gốc theo locale hiện tại
|
|
417
|
+
document.documentElement.dir = getHTMLTextDir(locale); // đặt thuộc tính dir của thẻ gốc theo locale hiện tại
|
|
418
|
+
}, [locale]);
|
|
419
|
+
};
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Sau đó sử dụng nó trong component gốc của bạn:
|
|
423
|
+
|
|
424
|
+
```tsx fileName="app/routes/layout.tsx"
|
|
425
|
+
import { Outlet } from "react-router";
|
|
426
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
427
|
+
|
|
428
|
+
import { useI18nHTMLAttributes } from "app/hooks/useI18nHTMLAttributes"; // nhập hook
|
|
429
|
+
|
|
430
|
+
export default function RootLayout() {
|
|
431
|
+
useI18nHTMLAttributes(); // gọi hook
|
|
432
|
+
|
|
433
|
+
return (
|
|
434
|
+
<IntlayerProvider>
|
|
435
|
+
<Outlet />
|
|
436
|
+
</IntlayerProvider>
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Bước 11: Thêm middleware (Tùy chọn)
|
|
442
|
+
|
|
443
|
+
Bạn cũng có thể sử dụng `intlayerProxy` để thêm routing phía server cho ứng dụng của bạn. Plugin này sẽ tự động phát hiện locale hiện tại dựa trên URL và thiết lập cookie locale phù hợp. Nếu không có locale nào được chỉ định, plugin sẽ xác định locale phù hợp nhất dựa trên ngôn ngữ trình duyệt của người dùng. Nếu không phát hiện được locale nào, nó sẽ chuyển hướng đến locale mặc định.
|
|
444
|
+
|
|
445
|
+
> Lưu ý rằng để sử dụng `intlayerProxy` trong môi trường production, bạn cần chuyển gói `vite-intlayer` từ `devDependencies` sang `dependencies`.
|
|
446
|
+
|
|
447
|
+
```typescript {3,7} fileName="vite.config.ts"
|
|
448
|
+
import { reactRouter } from "@react-router/dev/vite";
|
|
449
|
+
import { defineConfig } from "vite";
|
|
450
|
+
import { intlayer, intlayerProxy } from "vite-intlayer";
|
|
451
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
452
|
+
|
|
453
|
+
export default defineConfig({
|
|
454
|
+
plugins: [reactRouter(), tsconfigPaths(), intlayer(), intlayerProxy()],
|
|
455
|
+
});
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## Cấu hình TypeScript
|
|
461
|
+
|
|
462
|
+
Intlayer sử dụng module augmentation để tận dụng các lợi ích của TypeScript và làm cho codebase của bạn mạnh mẽ hơn.
|
|
463
|
+
|
|
464
|
+
Đảm bảo cấu hình TypeScript của bạn bao gồm các kiểu được tạo tự động:
|
|
465
|
+
|
|
466
|
+
```json5 fileName="tsconfig.json"
|
|
467
|
+
{
|
|
468
|
+
// ... các cấu hình hiện có của bạn
|
|
469
|
+
include: [
|
|
470
|
+
// ... các phần include hiện có của bạn
|
|
471
|
+
".intlayer/**/*.ts", // Bao gồm các kiểu được tạo tự động
|
|
472
|
+
],
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
## Cấu hình Git
|
|
479
|
+
|
|
480
|
+
Khuyến nghị bỏ qua các tệp được tạo bởi Intlayer. Điều này giúp bạn tránh việc commit chúng vào kho Git của mình.
|
|
481
|
+
|
|
482
|
+
Để làm điều này, bạn có thể thêm các hướng dẫn sau vào tệp `.gitignore` của bạn:
|
|
483
|
+
|
|
484
|
+
```plaintext fileName=".gitignore"
|
|
485
|
+
# Bỏ qua các tệp được tạo bởi Intlayer
|
|
486
|
+
.intlayer
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
## Tiện ích mở rộng VS Code
|
|
492
|
+
|
|
493
|
+
Để cải thiện trải nghiệm phát triển với Intlayer, bạn có thể cài đặt **Tiện ích mở rộng Intlayer cho VS Code** chính thức.
|
|
494
|
+
|
|
495
|
+
[Cài đặt từ VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)
|
|
496
|
+
|
|
497
|
+
Tiện ích mở rộng này cung cấp:
|
|
498
|
+
|
|
499
|
+
- **Tự động hoàn thành** cho các khóa dịch.
|
|
500
|
+
- **Phát hiện lỗi thời gian thực** cho các bản dịch bị thiếu.
|
|
501
|
+
- **Xem trước nội dung dịch ngay trong dòng**.
|
|
502
|
+
- **Hành động nhanh** để dễ dàng tạo và cập nhật bản dịch.
|
|
503
|
+
|
|
504
|
+
Để biết thêm chi tiết về cách sử dụng tiện ích mở rộng, hãy tham khảo [Tài liệu Tiện ích mở rộng VS Code của Intlayer](https://intlayer.org/doc/vs-code-extension).
|
|
505
|
+
|
|
506
|
+
---
|
|
507
|
+
|
|
508
|
+
## Đi xa hơn
|
|
509
|
+
|
|
510
|
+
Để đi xa hơn, bạn có thể triển khai [trình chỉnh sửa trực quan](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_visual_editor.md) hoặc tách nội dung của bạn ra ngoài bằng cách sử dụng [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/intlayer_CMS.md).
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
## Tham khảo Tài liệu
|
|
515
|
+
|
|
516
|
+
- [Tài liệu Intlayer](https://intlayer.org)
|
|
517
|
+
- [Tài liệu React Router v7](https://reactrouter.com/)
|
|
518
|
+
- [useIntlayer hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/react-intlayer/useIntlayer.md)
|
|
519
|
+
- [useLocale hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/react-intlayer/useLocale.md)
|
|
520
|
+
- [Khai báo nội dung](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/dictionary/content_file.md)
|
|
521
|
+
- [Cấu hình](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/configuration.md)
|
|
522
|
+
|
|
523
|
+
Hướng dẫn toàn diện này cung cấp tất cả những gì bạn cần để tích hợp Intlayer với React Router v7 cho một ứng dụng được quốc tế hóa hoàn chỉnh với định tuyến nhận biết locale và hỗ trợ TypeScript.
|
|
@@ -17,6 +17,7 @@ slugs:
|
|
|
17
17
|
- environment
|
|
18
18
|
- tanstack-start
|
|
19
19
|
applicationTemplate: https://github.com/aymericzip/intlayer-tanstack-start-template
|
|
20
|
+
youtubeVideo: https://www.youtube.com/watch?v=_XTdKVWaeqg
|
|
20
21
|
history:
|
|
21
22
|
- version: 7.3.9
|
|
22
23
|
date: 2025-12-05
|
|
@@ -586,19 +587,8 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
586
587
|
return getCookie(name, cookieString);
|
|
587
588
|
},
|
|
588
589
|
// Get the header from the request (default: 'x-intlayer-locale')
|
|
589
|
-
getHeader: (name) => getRequestHeader(name),
|
|
590
590
|
// Fallback using Accept-Language negotiation
|
|
591
|
-
|
|
592
|
-
const headers = getRequestHeaders();
|
|
593
|
-
const result: Record<string, string> = {};
|
|
594
|
-
|
|
595
|
-
// Convert the TypedHeaders into a plain Record<string, string>
|
|
596
|
-
for (const [key, value] of headers.entries()) {
|
|
597
|
-
result[key] = value;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
return result;
|
|
601
|
-
},
|
|
591
|
+
getHeader: (name) => getRequestHeader(name),
|
|
602
592
|
});
|
|
603
593
|
|
|
604
594
|
// Retrieve some content using getIntlayer()
|