@intlayer/docs 7.3.14 → 7.4.0

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.
Files changed (175) hide show
  1. package/blog/ar/intlayer_with_i18next.md +3 -0
  2. package/blog/ar/intlayer_with_next-i18next.md +3 -0
  3. package/blog/ar/intlayer_with_next-intl.md +3 -0
  4. package/blog/ar/intlayer_with_react-i18next.md +3 -0
  5. package/blog/ar/intlayer_with_react-intl.md +3 -0
  6. package/blog/ar/intlayer_with_vue-i18n.md +3 -0
  7. package/blog/de/intlayer_with_i18next.md +3 -0
  8. package/blog/de/intlayer_with_next-i18next.md +3 -0
  9. package/blog/de/intlayer_with_next-intl.md +3 -0
  10. package/blog/de/intlayer_with_react-i18next.md +3 -0
  11. package/blog/de/intlayer_with_react-intl.md +3 -0
  12. package/blog/de/intlayer_with_vue-i18n.md +3 -0
  13. package/blog/en/intlayer_with_i18next.md +7 -0
  14. package/blog/en/intlayer_with_next-i18next.md +3 -0
  15. package/blog/en/intlayer_with_next-intl.md +7 -0
  16. package/blog/en/intlayer_with_react-i18next.md +3 -0
  17. package/blog/en/intlayer_with_react-intl.md +3 -0
  18. package/blog/en/intlayer_with_vue-i18n.md +3 -0
  19. package/blog/en-GB/intlayer_with_i18next.md +3 -0
  20. package/blog/en-GB/intlayer_with_next-i18next.md +3 -0
  21. package/blog/en-GB/intlayer_with_next-intl.md +3 -0
  22. package/blog/en-GB/intlayer_with_react-i18next.md +3 -0
  23. package/blog/en-GB/intlayer_with_react-intl.md +3 -0
  24. package/blog/en-GB/intlayer_with_vue-i18n.md +3 -0
  25. package/blog/es/intlayer_with_i18next.md +3 -0
  26. package/blog/es/intlayer_with_next-i18next.md +3 -0
  27. package/blog/es/intlayer_with_next-intl.md +3 -0
  28. package/blog/es/intlayer_with_react-i18next.md +3 -0
  29. package/blog/es/intlayer_with_react-intl.md +3 -0
  30. package/blog/es/intlayer_with_vue-i18n.md +3 -0
  31. package/blog/fr/intlayer_with_i18next.md +3 -0
  32. package/blog/fr/intlayer_with_next-i18next.md +3 -0
  33. package/blog/fr/intlayer_with_next-intl.md +3 -0
  34. package/blog/fr/intlayer_with_react-i18next.md +3 -0
  35. package/blog/fr/intlayer_with_react-intl.md +3 -0
  36. package/blog/fr/intlayer_with_vue-i18n.md +3 -0
  37. package/blog/hi/intlayer_with_i18next.md +3 -0
  38. package/blog/hi/intlayer_with_next-i18next.md +3 -0
  39. package/blog/hi/intlayer_with_next-intl.md +3 -0
  40. package/blog/hi/intlayer_with_react-i18next.md +3 -0
  41. package/blog/hi/intlayer_with_react-intl.md +3 -0
  42. package/blog/hi/intlayer_with_vue-i18n.md +3 -0
  43. package/blog/id/intlayer_with_i18next.md +3 -0
  44. package/blog/id/intlayer_with_next-i18next.md +3 -0
  45. package/blog/id/intlayer_with_next-intl.md +3 -0
  46. package/blog/id/intlayer_with_react-i18next.md +3 -0
  47. package/blog/id/intlayer_with_react-intl.md +3 -0
  48. package/blog/id/intlayer_with_vue-i18n.md +3 -0
  49. package/blog/it/intlayer_with_i18next.md +3 -0
  50. package/blog/it/intlayer_with_next-i18next.md +3 -0
  51. package/blog/it/intlayer_with_next-intl.md +3 -0
  52. package/blog/it/intlayer_with_react-i18next.md +3 -0
  53. package/blog/it/intlayer_with_react-intl.md +3 -0
  54. package/blog/it/intlayer_with_vue-i18n.md +3 -0
  55. package/blog/ja/intlayer_with_i18next.md +3 -0
  56. package/blog/ja/intlayer_with_next-i18next.md +3 -0
  57. package/blog/ja/intlayer_with_next-intl.md +3 -0
  58. package/blog/ja/intlayer_with_react-i18next.md +3 -0
  59. package/blog/ja/intlayer_with_react-intl.md +3 -0
  60. package/blog/ja/intlayer_with_vue-i18n.md +3 -0
  61. package/blog/ko/intlayer_with_i18next.md +3 -0
  62. package/blog/ko/intlayer_with_next-i18next.md +3 -0
  63. package/blog/ko/intlayer_with_next-intl.md +3 -0
  64. package/blog/ko/intlayer_with_react-i18next.md +3 -0
  65. package/blog/ko/intlayer_with_react-intl.md +3 -0
  66. package/blog/ko/intlayer_with_vue-i18n.md +3 -0
  67. package/blog/pl/intlayer_with_i18next.md +3 -0
  68. package/blog/pl/intlayer_with_next-i18next.md +3 -0
  69. package/blog/pl/intlayer_with_next-intl.md +3 -0
  70. package/blog/pl/intlayer_with_react-i18next.md +3 -0
  71. package/blog/pl/intlayer_with_react-intl.md +3 -0
  72. package/blog/pl/intlayer_with_vue-i18n.md +3 -0
  73. package/blog/pt/intlayer_with_i18next.md +3 -0
  74. package/blog/pt/intlayer_with_next-i18next.md +3 -0
  75. package/blog/pt/intlayer_with_next-intl.md +3 -0
  76. package/blog/pt/intlayer_with_react-i18next.md +3 -0
  77. package/blog/pt/intlayer_with_react-intl.md +3 -0
  78. package/blog/pt/intlayer_with_vue-i18n.md +3 -0
  79. package/blog/ru/intlayer_with_i18next.md +3 -0
  80. package/blog/ru/intlayer_with_next-i18next.md +3 -0
  81. package/blog/ru/intlayer_with_next-intl.md +3 -0
  82. package/blog/ru/intlayer_with_react-i18next.md +3 -0
  83. package/blog/ru/intlayer_with_react-intl.md +3 -0
  84. package/blog/ru/intlayer_with_vue-i18n.md +3 -0
  85. package/blog/tr/intlayer_with_i18next.md +3 -0
  86. package/blog/tr/intlayer_with_next-i18next.md +3 -0
  87. package/blog/tr/intlayer_with_next-intl.md +3 -0
  88. package/blog/tr/intlayer_with_react-i18next.md +3 -0
  89. package/blog/tr/intlayer_with_vue-i18n.md +3 -0
  90. package/blog/vi/intlayer_with_i18next.md +3 -0
  91. package/blog/vi/intlayer_with_next-i18next.md +3 -0
  92. package/blog/vi/intlayer_with_next-intl.md +3 -0
  93. package/blog/vi/intlayer_with_react-i18next.md +3 -0
  94. package/blog/vi/intlayer_with_react-intl.md +3 -0
  95. package/blog/vi/intlayer_with_vue-i18n.md +3 -0
  96. package/blog/zh/intlayer_with_i18next.md +3 -0
  97. package/blog/zh/intlayer_with_next-i18next.md +3 -0
  98. package/blog/zh/intlayer_with_next-intl.md +3 -0
  99. package/blog/zh/intlayer_with_react-i18next.md +3 -0
  100. package/blog/zh/intlayer_with_react-intl.md +3 -0
  101. package/blog/zh/intlayer_with_vue-i18n.md +3 -0
  102. package/docs/ar/intlayer_with_lynx+react.md +1 -1
  103. package/docs/ar/intlayer_with_tanstack.md +132 -2
  104. package/docs/ar/intlayer_with_vite+react.md +99 -331
  105. package/docs/ar/plugins/sync-json.md +3 -0
  106. package/docs/de/intlayer_with_lynx+react.md +1 -1
  107. package/docs/de/intlayer_with_tanstack.md +132 -2
  108. package/docs/de/intlayer_with_vite+react.md +116 -380
  109. package/docs/de/plugins/sync-json.md +3 -0
  110. package/docs/en/intlayer_with_tanstack.md +131 -1
  111. package/docs/en/intlayer_with_vite+react.md +6 -10
  112. package/docs/en/plugins/sync-json.md +3 -0
  113. package/docs/en-GB/intlayer_with_tanstack.md +131 -1
  114. package/docs/en-GB/intlayer_with_vite+react.md +62 -74
  115. package/docs/en-GB/plugins/sync-json.md +3 -0
  116. package/docs/es/intlayer_with_tanstack.md +132 -2
  117. package/docs/es/intlayer_with_vite+react.md +101 -333
  118. package/docs/es/plugins/sync-json.md +3 -0
  119. package/docs/fr/intlayer_with_tanstack.md +132 -2
  120. package/docs/fr/intlayer_with_vite+react.md +101 -357
  121. package/docs/fr/plugins/sync-json.md +3 -0
  122. package/docs/hi/intlayer_with_tanstack.md +132 -2
  123. package/docs/hi/intlayer_with_vite+react.md +120 -333
  124. package/docs/hi/plugins/sync-json.md +3 -0
  125. package/docs/id/intlayer_with_tanstack.md +132 -2
  126. package/docs/id/intlayer_with_vite+react.md +7 -13
  127. package/docs/id/plugins/sync-json.md +3 -0
  128. package/docs/it/intlayer_with_lynx+react.md +1 -1
  129. package/docs/it/intlayer_with_tanstack.md +132 -2
  130. package/docs/it/intlayer_with_vite+react.md +121 -393
  131. package/docs/it/plugins/sync-json.md +3 -0
  132. package/docs/ja/intlayer_with_tanstack.md +132 -2
  133. package/docs/ja/intlayer_with_vite+react.md +106 -378
  134. package/docs/ja/plugins/sync-json.md +3 -0
  135. package/docs/ko/intlayer_with_lynx+react.md +1 -1
  136. package/docs/ko/intlayer_with_tanstack.md +132 -2
  137. package/docs/ko/intlayer_with_vite+react.md +90 -322
  138. package/docs/ko/plugins/sync-json.md +3 -0
  139. package/docs/pl/intlayer_with_tanstack.md +132 -2
  140. package/docs/pl/intlayer_with_vite+react.md +25 -21
  141. package/docs/pl/plugins/sync-json.md +3 -0
  142. package/docs/pt/intlayer_with_tanstack.md +132 -2
  143. package/docs/pt/intlayer_with_vite+react.md +96 -328
  144. package/docs/pt/plugins/sync-json.md +3 -0
  145. package/docs/ru/intlayer_with_lynx+react.md +1 -1
  146. package/docs/ru/intlayer_with_tanstack.md +132 -2
  147. package/docs/ru/intlayer_with_vite+react.md +109 -362
  148. package/docs/ru/plugins/sync-json.md +3 -0
  149. package/docs/tr/intlayer_with_tanstack.md +132 -2
  150. package/docs/tr/intlayer_with_vite+react.md +132 -366
  151. package/docs/tr/plugins/sync-json.md +3 -0
  152. package/docs/vi/intlayer_with_tanstack.md +132 -2
  153. package/docs/vi/intlayer_with_vite+react.md +16 -19
  154. package/docs/vi/plugins/sync-json.md +3 -0
  155. package/docs/zh/intlayer_with_tanstack.md +133 -3
  156. package/docs/zh/intlayer_with_vite+react.md +91 -374
  157. package/docs/zh/plugins/sync-json.md +3 -0
  158. package/frequent_questions/ar/customized_locale_list.md +1 -1
  159. package/frequent_questions/de/customized_locale_list.md +1 -1
  160. package/frequent_questions/en/customized_locale_list.md +1 -1
  161. package/frequent_questions/en-GB/customized_locale_list.md +1 -1
  162. package/frequent_questions/es/customized_locale_list.md +1 -1
  163. package/frequent_questions/fr/customized_locale_list.md +1 -1
  164. package/frequent_questions/hi/customized_locale_list.md +1 -1
  165. package/frequent_questions/id/customized_locale_list.md +1 -1
  166. package/frequent_questions/it/customized_locale_list.md +1 -1
  167. package/frequent_questions/ja/customized_locale_list.md +1 -1
  168. package/frequent_questions/ko/customized_locale_list.md +1 -1
  169. package/frequent_questions/pl/customized_locale_list.md +1 -1
  170. package/frequent_questions/pt/customized_locale_list.md +1 -1
  171. package/frequent_questions/ru/customized_locale_list.md +1 -1
  172. package/frequent_questions/tr/customized_locale_list.md +1 -1
  173. package/frequent_questions/vi/customized_locale_list.md +1 -1
  174. package/frequent_questions/zh/customized_locale_list.md +1 -1
  175. package/package.json +6 -6
@@ -22,6 +22,7 @@ slugs:
22
22
  - doc
23
23
  - plugin
24
24
  - sync-json
25
+ youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
25
26
  history:
26
27
  - version: 6.1.6
27
28
  date: 2025-10-05
@@ -30,6 +31,8 @@ history:
30
31
 
31
32
  # JSON Senkronizasyonu (i18n köprüleri)
32
33
 
34
+ <iframe title="JSON çevirilerinizi Intlayer ile nasıl senkronize tutarsınız" 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/MpGMxniDHNg?autoplay=0&amp;origin=http://intlayer.org&amp;controls=0&amp;rel=1"/>
35
+
33
36
  Intlayer'ı mevcut i18n yapınıza bir eklenti olarak kullanın. Bu eklenti, JSON mesajlarınızı Intlayer sözlükleriyle senkronize tutar, böylece:
34
37
 
35
38
  - i18next, next-intl, react-intl, vue-i18n, next-translate, nuxt-i18n, Solid-i18next, svelte-i18n vb. kullanmaya devam edebilirsiniz.
@@ -19,9 +19,12 @@ slugs:
19
19
  applicationTemplate: https://github.com/aymericzip/intlayer-tanstack-start-template
20
20
  youtubeVideo: https://www.youtube.com/watch?v=_XTdKVWaeqg
21
21
  history:
22
+ - version: 7.4.0
23
+ date: 2025-12-11
24
+ changes: Giới thiệu validatePrefix và thêm bước 14: Xử lý trang 404 với các tuyến đường được bản địa hóa.
22
25
  - version: 7.3.9
23
26
  date: 2025-12-05
24
- changes: Add step 13: Retrieve the locale in your server actions (Optional)
27
+ changes: Thêm bước 13: Lấy locale trong server actions của bạn (Tùy chọn)
25
28
  - version: 6.5.2
26
29
  date: 2025-10-03
27
30
  changes: Cập nhật tài liệu
@@ -600,7 +603,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
600
603
 
601
604
  ---
602
605
 
603
- ### Bước 14: Cấu hình TypeScript (Tùy chọn)
606
+ ### Bước 14: Quản trang không tìm thấy (Tùy chọn)
607
+
608
+ Khi người dùng truy cập một trang không tồn tại, bạn có thể hiển thị một trang không tìm thấy tùy chỉnh và tiền tố locale có thể ảnh hưởng đến cách trang không tìm thấy được kích hoạt.
609
+
610
+ #### Hiểu về xử lý 404 của TanStack Router với tiền tố locale
611
+
612
+ Trong TanStack Router, xử lý các trang 404 với các route đã được bản địa hóa yêu cầu một cách tiếp cận nhiều lớp:
613
+
614
+ 1. **Route 404 chuyên dụng**: Một route cụ thể để hiển thị giao diện 404
615
+ 2. **Xác thực cấp route**: Xác thực các tiền tố locale và chuyển hướng các tiền tố không hợp lệ đến 404
616
+ 3. **Route catch-all**: Bắt tất cả các đường dẫn không khớp trong phân đoạn locale
617
+
618
+ ```tsx fileName="src/routes/{-$locale}/404.tsx"
619
+ import { createFileRoute } from "@tanstack/react-router";
620
+
621
+ // Điều này tạo một tuyến đường /[locale]/404 chuyên dụng
622
+ // Nó được sử dụng cả như một tuyến đường trực tiếp và được nhập như một thành phần trong các tệp khác
623
+ export const Route = createFileRoute("/{-$locale}/404")({
624
+ component: NotFoundComponent,
625
+ });
626
+
627
+ // Xuất riêng để có thể tái sử dụng trong notFoundComponent và các tuyến catch-all
628
+ export function NotFoundComponent() {
629
+ return (
630
+ <div>
631
+ <h1>404</h1>
632
+ </div>
633
+ );
634
+ }
635
+ ```
636
+
637
+ ```tsx fileName="src/routes/__root.tsx"
638
+ import { createRootRoute } from "@tanstack/react-router";
639
+
640
+ // Tuyến đường gốc phục vụ như bố cục cấp cao nhất
641
+ // Nó không xử lý 404 trực tiếp - điều đó được ủy quyền cho các tuyến đường con
642
+ // Điều này giữ cho gốc đơn giản và cho phép các tuyến đường nhận biết locale quản lý logic 404 của riêng chúng
643
+ export const Route = createRootRoute({
644
+ component: Outlet,
645
+ });
646
+ ```
647
+
648
+ ```tsx fileName="src/routes/{-$locale}/route.tsx"
649
+ import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
650
+ import { validatePrefix } from "intlayer";
651
+ import { IntlayerProvider, useLocale } from "react-intlayer";
652
+
653
+ import { LocaleSwitcher } from "@/components/locale-switcher";
654
+ import { NotFoundComponent } from "./404";
655
+
656
+ export const Route = createFileRoute("/{-$locale}")({
657
+ // beforeLoad chạy trước khi tuyến đường được kết xuất (trên cả máy chủ và máy khách)
658
+ // Đây là nơi lý tưởng để xác thực tiền tố locale
659
+ beforeLoad: ({ params }) => {
660
+ // Lấy locale từ tham số tuyến đường (không phải từ tiêu đề máy chủ, vì beforeLoad chạy trên cả máy khách và máy chủ)
661
+ const localeParam = params.locale;
662
+
663
+ // validatePrefix kiểm tra xem locale có hợp lệ theo cấu hình intlayer của bạn không
664
+ // Trả về: { isValid: boolean, localePrefix: string }
665
+ // - isValid: true nếu tiền tố khớp với locale đã cấu hình (hoặc trống khi tiền tố là tùy chọn)
666
+ // - localePrefix: tiền tố đã được xác thực hoặc tiền tố locale mặc định để chuyển hướng
667
+ const { isValid, localePrefix } = validatePrefix(localeParam);
668
+
669
+ if (isValid) {
670
+ // Locale hợp lệ, cho phép tuyến đường kết xuất bình thường
671
+ return;
672
+ }
673
+
674
+ // Tiền tố locale không hợp lệ (ví dụ: /xyz/about trong đó "xyz" không phải là locale hợp lệ)
675
+ // Chuyển hướng đến trang 404 với tiền tố locale hợp lệ
676
+ // Điều này đảm bảo trang 404 vẫn được bản địa hóa đúng cách
677
+ throw redirect({
678
+ to: "/{-$locale}/404",
679
+ params: { locale: localePrefix },
680
+ });
681
+ },
682
+ component: RouteComponent,
683
+ // notFoundComponent được gọi khi một tuyến đường con không tồn tại
684
+ // ví dụ: /en/trang-khong-ton-tai kích hoạt điều này trong bố cục /en
685
+ notFoundComponent: NotFoundLayout,
686
+ });
687
+
688
+ function RouteComponent() {
689
+ const { defaultLocale } = useLocale();
690
+ const { locale } = Route.useParams();
691
+
692
+ return (
693
+ // Bọc toàn bộ phân đoạn locale bằng IntlayerProvider
694
+ // Quay lại defaultLocale khi tham số locale là undefined (chế độ tiền tố tùy chọn)
695
+ <IntlayerProvider locale={locale ?? defaultLocale}>
696
+ <Outlet />
697
+ </IntlayerProvider>
698
+ );
699
+ }
700
+
701
+ // NotFoundLayout bọc thành phần 404 bằng IntlayerProvider
702
+ // Điều này đảm bảo bản dịch vẫn hoạt động trên trang 404
703
+ function NotFoundLayout() {
704
+ const { defaultLocale } = useLocale();
705
+ const { locale } = Route.useParams();
706
+
707
+ return (
708
+ <IntlayerProvider locale={locale ?? defaultLocale}>
709
+ <NotFoundComponent />
710
+ {/* Bao gồm LocaleSwitcher để người dùng có thể thay đổi ngôn ngữ ngay cả trên 404 */}
711
+ <LocaleSwitcher />
712
+ </IntlayerProvider>
713
+ );
714
+ }
715
+ ```
716
+
717
+ ```tsx fileName="src/routes/{-$locale}/$.tsx"
718
+ import { createFileRoute } from "@tanstack/react-router";
719
+
720
+ import { NotFoundComponent } from "./404";
721
+
722
+ // Tuyến đường $ (splat/catch-all) khớp với bất kỳ đường dẫn nào không khớp với các tuyến đường khác
723
+ // ví dụ: /en/mot/duong/dan/sau/long/khong-hop-le
724
+ // Điều này đảm bảo TẤT CẢ các đường dẫn không khớp trong một locale hiển thị trang 404
725
+ // Nếu không có điều này, các đường dẫn sâu không khớp có thể hiển thị trang trống hoặc lỗi
726
+ export const Route = createFileRoute("/{-$locale}/$")({
727
+ component: NotFoundComponent,
728
+ });
729
+ ```
730
+
731
+ ---
732
+
733
+ ### Bước 15: Cấu hình TypeScript (Tùy chọn)
604
734
 
605
735
  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.
606
736
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2024-03-07
3
- updatedAt: 2024-03-07
3
+ updatedAt: 2025-12-10
4
4
  title: Cách dịch ứng dụng Vite và React của bạn – Hướng dẫn i18n 2025
5
5
  description: Tìm hiểu cách thêm quốc tế hóa (i18n) vào ứng dụng Vite và React của bạn bằng cách sử dụng Intlayer. Theo dõi hướng dẫn này để làm cho ứng dụng của bạn đa ngôn ngữ.
6
6
  keywords:
@@ -86,7 +86,7 @@ yarn add vite-intlayer --save-dev
86
86
 
87
87
  - **intlayer**
88
88
 
89
- 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).
89
+ 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/en/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/en/cli/index.md).
90
90
 
91
91
  - **react-intlayer**
92
92
  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.
@@ -154,7 +154,7 @@ const config = {
154
154
  module.exports = config;
155
155
  ```
156
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).
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/en/configuration.md).
158
158
 
159
159
  ### Bước 3: Tích hợp Intlayer vào cấu hình Vite của bạn
160
160
 
@@ -441,7 +441,7 @@ module.exports = appContent;
441
441
 
442
442
  > 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à `./src`). Và phù hợp với phần mở rộng tệp khai báo nội dung (mặc định là `.content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}`).
443
443
 
444
- > Để 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).
444
+ > Để 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/en/dictionary/content_file.md).
445
445
 
446
446
  > Nếu tệp nội dung của bạn bao gồm mã TSX, bạn nên xem xét việc import `import React from "react";` trong tệp nội dung của bạn.
447
447
 
@@ -596,7 +596,7 @@ module.exports = App;
596
596
  > <img src={content.image.src.value} alt={content.image.value} />
597
597
  > ```
598
598
 
599
- > Để 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).
599
+ > Để 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/en/packages/react-intlayer/useIntlayer.md).
600
600
 
601
601
  ### (Tùy chọn) Bước 6: Thay đổi ngôn ngữ cho nội dung của bạn
602
602
 
@@ -648,7 +648,7 @@ const LocaleSwitcher = () => {
648
648
  };
649
649
  ```
650
650
 
651
- > Để tìm hiểu thêm về hook `useLocale`, hãy tham khảo [tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/react-intlayer/useLocale.md).
651
+ > Để tìm hiểu thêm về hook `useLocale`, hãy tham khảo [tài liệu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/react-intlayer/useLocale.md).
652
652
 
653
653
  ### (Tùy chọn) Bước 7: Thêm định tuyến theo ngôn ngữ vào ứng dụng của bạn
654
654
 
@@ -661,7 +661,7 @@ Ví dụ:
661
661
  - https://example.com/fr/about
662
662
  ```
663
663
 
664
- > Theo mặc định, các tuyến đường không được thêm tiền tố cho ngôn ngữ mặc định. Nếu bạn muốn thêm tiền tố cho ngôn ngữ mặc định, bạn có thể đặt tùy chọn `middleware.prefixDefault` thành `true` trong cấu hình của bạn. Xem thêm tại [tài liệu cấu hình](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/configuration.md) để biết thêm thông tin.
664
+ > Theo mặc định, các tuyến đường không được thêm tiền tố cho ngôn ngữ mặc định. Nếu bạn muốn thêm tiền tố cho ngôn ngữ mặc định, bạn có thể đặt tùy chọn `middleware.prefixDefault` thành `true` trong cấu hình của bạn. Xem thêm tại [tài liệu cấu hình](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/configuration.md) để biết thêm thông tin.
665
665
 
666
666
  Để thêm định tuyến theo ngôn ngữ vào ứng dụng của bạn, bạn có thể tạo một thành phần `LocaleRouter` bao bọc các tuyến đường của ứng dụng và xử lý định tuyến dựa trên ngôn ngữ. Dưới đây là ví dụ sử dụng [React Router](https://reactrouter.com/home):
667
667
 
@@ -1025,10 +1025,10 @@ const LocaleSwitcher = () => {
1025
1025
 
1026
1026
  > Tham khảo tài liệu:
1027
1027
  >
1028
- > - [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/react-intlayer/useLocale.md)
1029
- > - [`getLocaleName` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/intlayer/getLocaleName.md)
1030
- > - [`getLocalizedUrl` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/intlayer/getLocalizedUrl.md)
1031
- > - [`getHTMLTextDir` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/vi/packages/intlayer/getHTMLTextDir.md)
1028
+ > - [`useLocale` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/react-intlayer/useLocale.md)
1029
+ > - [`getLocaleName` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/intlayer/getLocaleName.md)
1030
+ > - [`getLocalizedUrl` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/intlayer/getLocalizedUrl.md)
1031
+ > - [`getHTMLTextDir` hook](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/packages/intlayer/getHTMLTextDir.md)
1032
1032
  > - [`hrefLang` attribute](https://developers.google.com/search/docs/specialty/international/localized-versions?hl=fr)
1033
1033
  > - [`lang` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang)
1034
1034
  > - [`dir` attribute`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir)
@@ -1225,11 +1225,10 @@ import {
1225
1225
  } from "react";
1226
1226
  import { useLocale } from "react-intlayer";
1227
1227
 
1228
- export interface LinkProps
1229
- extends DetailedHTMLProps<
1230
- AnchorHTMLAttributes<HTMLAnchorElement>,
1231
- HTMLAnchorElement
1232
- > {}
1228
+ export interface LinkProps extends DetailedHTMLProps<
1229
+ AnchorHTMLAttributes<HTMLAnchorElement>,
1230
+ HTMLAnchorElement
1231
+ > {}
1233
1232
 
1234
1233
  /**
1235
1234
  * Hàm tiện ích để kiểm tra xem một URL có phải là liên kết ngoài không.
@@ -1402,6 +1401,4 @@ Tiện ích mở rộng này cung cấp:
1402
1401
 
1403
1402
  ### Tiến xa hơn
1404
1403
 
1405
- Để tiến xa hơn, bạn có thể triển khai [trình soạn thảo 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).
1406
-
1407
- ---
1404
+ Để tiến xa hơn, bạn có thể triển khai [trình soạn thảo trực quan](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/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/en/intlayer_CMS.md).
@@ -22,6 +22,7 @@ slugs:
22
22
  - doc
23
23
  - plugin
24
24
  - sync-json
25
+ youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
25
26
  history:
26
27
  - version: 6.1.6
27
28
  date: 2025-10-05
@@ -30,6 +31,8 @@ history:
30
31
 
31
32
  # Đồng bộ JSON (cầu nối i18n)
32
33
 
34
+ <iframe title="Cách giữ bản dịch JSON của bạn đồng bộ với 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/MpGMxniDHNg?autoplay=0&amp;origin=http://intlayer.org&amp;controls=0&amp;rel=1"/>
35
+
33
36
  Sử dụng Intlayer như một tiện ích bổ sung cho bộ công cụ i18n hiện có của bạn. Plugin này giữ cho các thông điệp JSON của bạn đồng bộ với từ điển Intlayer để bạn có thể:
34
37
 
35
38
  - Giữ nguyên i18next, next-intl, react-intl, vue-i18n, next-translate, nuxt-i18n, Solid-i18next, svelte-i18n, v.v.
@@ -19,9 +19,12 @@ slugs:
19
19
  applicationTemplate: https://github.com/aymericzip/intlayer-tanstack-start-template
20
20
  youtubeVideo: https://www.youtube.com/watch?v=_XTdKVWaeqg
21
21
  history:
22
+ - version: 7.4.0
23
+ date: 2025-12-11
24
+ changes: 引入 validatePrefix 并添加步骤 14: 处理带有本地化路由的 404 页面。
22
25
  - version: 7.3.9
23
26
  date: 2025-12-05
24
- changes: Add step 13: Retrieve the locale in your server actions (Optional)
27
+ changes: 添加步骤 13: 在您的 server actions 中获取 locale (可选)
25
28
  - version: 5.8.1
26
29
  date: 2025-09-09
27
30
  changes: 为 Tanstack Start 添加支持
@@ -237,7 +240,7 @@ export default appContent;
237
240
  import type { FC } from "react";
238
241
 
239
242
  import { Link, type LinkComponentProps } from "@tanstack/react-router";
240
- import { useLocale } from "intlayer";
243
+ import { useLocale } from "react-intlayer";
241
244
 
242
245
  export const LOCALE_ROUTE = "{-$locale}" as const;
243
246
 
@@ -591,7 +594,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
591
594
 
592
595
  ---
593
596
 
594
- ### 第14步:配置 TypeScript(可选)
597
+ ### 第14步:管理未找到的页面(可选)
598
+
599
+ 当用户访问不存在的页面时,您可以显示自定义的未找到页面,并且区域设置前缀可能会影响未找到页面的触发方式。
600
+
601
+ #### 了解 TanStack Router 使用区域设置前缀的 404 处理
602
+
603
+ 在 TanStack Router 中,使用本地化路由处理 404 页面需要采用多层方法:
604
+
605
+ 1. **专用 404 路由**:用于显示 404 UI 的特定路由
606
+ 2. **路由级验证**:验证区域设置前缀并将无效的前缀重定向到 404
607
+ 3. **捕获所有路由**:捕获区域设置段内任何不匹配的路径
608
+
609
+ ```tsx fileName="src/routes/{-$locale}/404.tsx"
610
+ import { createFileRoute } from "@tanstack/react-router";
611
+
612
+ // 这将创建一个专用的 /[locale]/404 路由
613
+ // 它既作为直接路由使用,也可以在其他文件中作为组件导入
614
+ export const Route = createFileRoute("/{-$locale}/404")({
615
+ component: NotFoundComponent,
616
+ });
617
+
618
+ // 单独导出,以便可以在 notFoundComponent 和 catch-all 路由中重用
619
+ export function NotFoundComponent() {
620
+ return (
621
+ <div>
622
+ <h1>404</h1>
623
+ </div>
624
+ );
625
+ }
626
+ ```
627
+
628
+ ```tsx fileName="src/routes/__root.tsx"
629
+ import { createRootRoute } from "@tanstack/react-router";
630
+
631
+ // 根路由作为顶级布局
632
+ // 它不直接处理 404 - 这被委托给子路由
633
+ // 这使根路由保持简单,并让区域设置感知的路由管理自己的 404 逻辑
634
+ export const Route = createRootRoute({
635
+ component: Outlet,
636
+ });
637
+ ```
638
+
639
+ ```tsx fileName="src/routes/{-$locale}/route.tsx"
640
+ import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
641
+ import { validatePrefix } from "intlayer";
642
+ import { IntlayerProvider, useLocale } from "react-intlayer";
643
+
644
+ import { LocaleSwitcher } from "@/components/locale-switcher";
645
+ import { NotFoundComponent } from "./404";
646
+
647
+ export const Route = createFileRoute("/{-$locale}")({
648
+ // beforeLoad 在路由渲染之前运行(在服务器和客户端上)
649
+ // 这是验证区域设置前缀的理想位置
650
+ beforeLoad: ({ params }) => {
651
+ // 从路由参数获取区域设置(不是从服务器标头,因为 beforeLoad 在客户端和服务器上都会运行)
652
+ const localeParam = params.locale;
653
+
654
+ // validatePrefix 检查区域设置是否根据您的 intlayer 配置有效
655
+ // 返回: { isValid: boolean, localePrefix: string }
656
+ // - isValid: 如果前缀匹配配置的区域设置(或当前缀可选时为空),则为 true
657
+ // - localePrefix: 已验证的前缀或用于重定向的默认区域设置前缀
658
+ const { isValid, localePrefix } = validatePrefix(localeParam);
659
+
660
+ if (isValid) {
661
+ // 区域设置有效,允许路由正常渲染
662
+ return;
663
+ }
664
+
665
+ // 无效的区域设置前缀(例如,/xyz/about 其中 "xyz" 不是有效的区域设置)
666
+ // 重定向到具有有效区域设置前缀的 404 页面
667
+ // 这确保 404 页面仍然正确本地化
668
+ throw redirect({
669
+ to: "/{-$locale}/404",
670
+ params: { locale: localePrefix },
671
+ });
672
+ },
673
+ component: RouteComponent,
674
+ // notFoundComponent 在子路由不存在时被调用
675
+ // 例如,/en/不存在的页面 在 /en 布局内触发此操作
676
+ notFoundComponent: NotFoundLayout,
677
+ });
678
+
679
+ function RouteComponent() {
680
+ const { defaultLocale } = useLocale();
681
+ const { locale } = Route.useParams();
682
+
683
+ return (
684
+ // 用 IntlayerProvider 包装整个区域设置段
685
+ // 当区域设置参数为 undefined 时回退到 defaultLocale(可选前缀模式)
686
+ <IntlayerProvider locale={locale ?? defaultLocale}>
687
+ <Outlet />
688
+ </IntlayerProvider>
689
+ );
690
+ }
691
+
692
+ // NotFoundLayout 用 IntlayerProvider 包装 404 组件
693
+ // 这确保翻译在 404 页面上仍然有效
694
+ function NotFoundLayout() {
695
+ const { defaultLocale } = useLocale();
696
+ const { locale } = Route.useParams();
697
+
698
+ return (
699
+ <IntlayerProvider locale={locale ?? defaultLocale}>
700
+ <NotFoundComponent />
701
+ {/* 包含 LocaleSwitcher,以便用户即使在 404 页面上也可以更改语言 */}
702
+ <LocaleSwitcher />
703
+ </IntlayerProvider>
704
+ );
705
+ }
706
+ ```
707
+
708
+ ```tsx fileName="src/routes/{-$locale}/$.tsx"
709
+ import { createFileRoute } from "@tanstack/react-router";
710
+
711
+ import { NotFoundComponent } from "./404";
712
+
713
+ // $ (splat/catch-all) 路由匹配任何与其他路由不匹配的路径
714
+ // 例如,/en/某个/深度/嵌套/无效/路径
715
+ // 这确保区域设置内所有不匹配的路径都显示 404 页面
716
+ // 没有这个,不匹配的深层路径可能会显示空白页面或错误
717
+ export const Route = createFileRoute("/{-$locale}/$")({
718
+ component: NotFoundComponent,
719
+ });
720
+ ```
721
+
722
+ ---
723
+
724
+ ### 第15步:配置 TypeScript(可选)
595
725
 
596
726
  Intlayer 使用模块增强来利用 TypeScript 的优势,使您的代码库更健壮。
597
727