@intlayer/docs 7.3.15 → 7.5.0-canary.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.
- package/blog/ar/intlayer_with_i18next.md +2 -0
- package/blog/ar/intlayer_with_next-i18next.md +2 -0
- package/blog/ar/intlayer_with_next-intl.md +2 -0
- package/blog/ar/intlayer_with_react-i18next.md +2 -0
- package/blog/ar/intlayer_with_react-intl.md +2 -0
- package/blog/ar/intlayer_with_vue-i18n.md +2 -0
- package/blog/de/intlayer_with_i18next.md +2 -0
- package/blog/de/intlayer_with_next-i18next.md +1 -0
- package/blog/de/intlayer_with_next-intl.md +2 -0
- package/blog/de/intlayer_with_react-i18next.md +2 -0
- package/blog/de/intlayer_with_react-intl.md +2 -0
- package/blog/de/intlayer_with_vue-i18n.md +2 -0
- package/blog/en/intlayer_with_i18next.md +6 -0
- package/blog/en/intlayer_with_next-i18next.md +3 -0
- package/blog/en/intlayer_with_next-intl.md +3 -0
- package/blog/en/intlayer_with_react-i18next.md +3 -0
- package/blog/en/intlayer_with_react-intl.md +3 -0
- package/blog/en/intlayer_with_vue-i18n.md +3 -0
- package/blog/en-GB/intlayer_with_i18next.md +2 -0
- package/blog/en-GB/intlayer_with_next-i18next.md +2 -0
- package/blog/en-GB/intlayer_with_next-intl.md +2 -0
- package/blog/en-GB/intlayer_with_react-i18next.md +2 -0
- package/blog/en-GB/intlayer_with_react-intl.md +2 -0
- package/blog/en-GB/intlayer_with_vue-i18n.md +2 -0
- package/blog/es/intlayer_with_i18next.md +2 -0
- package/blog/es/intlayer_with_next-i18next.md +2 -0
- package/blog/es/intlayer_with_next-intl.md +2 -0
- package/blog/es/intlayer_with_react-i18next.md +2 -0
- package/blog/es/intlayer_with_react-intl.md +2 -0
- package/blog/es/intlayer_with_vue-i18n.md +2 -0
- package/blog/fr/intlayer_with_i18next.md +2 -0
- package/blog/fr/intlayer_with_next-i18next.md +2 -0
- package/blog/fr/intlayer_with_next-intl.md +2 -0
- package/blog/fr/intlayer_with_react-i18next.md +2 -0
- package/blog/fr/intlayer_with_react-intl.md +2 -0
- package/blog/fr/intlayer_with_vue-i18n.md +2 -0
- package/blog/hi/intlayer_with_i18next.md +2 -0
- package/blog/hi/intlayer_with_next-i18next.md +2 -0
- package/blog/hi/intlayer_with_next-intl.md +2 -0
- package/blog/hi/intlayer_with_react-i18next.md +2 -0
- package/blog/hi/intlayer_with_react-intl.md +2 -0
- package/blog/hi/intlayer_with_vue-i18n.md +2 -0
- package/blog/id/intlayer_with_i18next.md +2 -0
- package/blog/id/intlayer_with_next-i18next.md +2 -0
- package/blog/id/intlayer_with_next-intl.md +2 -0
- package/blog/id/intlayer_with_react-i18next.md +2 -0
- package/blog/id/intlayer_with_react-intl.md +2 -0
- package/blog/id/intlayer_with_vue-i18n.md +2 -0
- package/blog/it/intlayer_with_i18next.md +2 -0
- package/blog/it/intlayer_with_next-i18next.md +2 -0
- package/blog/it/intlayer_with_next-intl.md +2 -0
- package/blog/it/intlayer_with_react-i18next.md +2 -0
- package/blog/it/intlayer_with_react-intl.md +2 -0
- package/blog/it/intlayer_with_vue-i18n.md +2 -0
- package/blog/ja/intlayer_with_i18next.md +2 -0
- package/blog/ja/intlayer_with_next-i18next.md +1 -0
- package/blog/ja/intlayer_with_next-intl.md +2 -0
- package/blog/ja/intlayer_with_react-i18next.md +2 -0
- package/blog/ja/intlayer_with_react-intl.md +2 -0
- package/blog/ja/intlayer_with_vue-i18n.md +2 -0
- package/blog/ko/intlayer_with_i18next.md +2 -0
- package/blog/ko/intlayer_with_next-i18next.md +2 -0
- package/blog/ko/intlayer_with_next-intl.md +2 -0
- package/blog/ko/intlayer_with_react-i18next.md +2 -0
- package/blog/ko/intlayer_with_react-intl.md +2 -0
- package/blog/ko/intlayer_with_vue-i18n.md +2 -0
- package/blog/pl/intlayer_with_i18next.md +2 -0
- package/blog/pl/intlayer_with_next-i18next.md +2 -0
- package/blog/pl/intlayer_with_next-intl.md +2 -0
- package/blog/pl/intlayer_with_react-i18next.md +2 -0
- package/blog/pl/intlayer_with_react-intl.md +2 -0
- package/blog/pl/intlayer_with_vue-i18n.md +2 -0
- package/blog/pt/intlayer_with_i18next.md +2 -0
- package/blog/pt/intlayer_with_next-i18next.md +2 -0
- package/blog/pt/intlayer_with_next-intl.md +2 -0
- package/blog/pt/intlayer_with_react-i18next.md +2 -0
- package/blog/pt/intlayer_with_react-intl.md +2 -0
- package/blog/pt/intlayer_with_vue-i18n.md +2 -0
- package/blog/ru/intlayer_with_i18next.md +2 -0
- package/blog/ru/intlayer_with_next-i18next.md +2 -0
- package/blog/ru/intlayer_with_next-intl.md +2 -0
- package/blog/ru/intlayer_with_react-i18next.md +2 -0
- package/blog/ru/intlayer_with_react-intl.md +2 -0
- package/blog/ru/intlayer_with_vue-i18n.md +2 -0
- package/blog/tr/intlayer_with_i18next.md +2 -0
- package/blog/tr/intlayer_with_next-i18next.md +2 -0
- package/blog/tr/intlayer_with_next-intl.md +2 -0
- package/blog/tr/intlayer_with_react-i18next.md +2 -0
- package/blog/tr/intlayer_with_react-intl.md +2 -0
- package/blog/tr/intlayer_with_vue-i18n.md +2 -0
- package/blog/vi/intlayer_with_i18next.md +2 -0
- package/blog/vi/intlayer_with_next-i18next.md +2 -0
- package/blog/vi/intlayer_with_next-intl.md +2 -0
- package/blog/vi/intlayer_with_react-i18next.md +2 -0
- package/blog/vi/intlayer_with_react-intl.md +2 -0
- package/blog/vi/intlayer_with_vue-i18n.md +2 -0
- package/blog/zh/intlayer_with_i18next.md +2 -0
- package/blog/zh/intlayer_with_next-i18next.md +2 -0
- package/blog/zh/intlayer_with_next-intl.md +2 -0
- package/blog/zh/intlayer_with_react-i18next.md +2 -0
- package/blog/zh/intlayer_with_react-intl.md +2 -0
- package/blog/zh/intlayer_with_vue-i18n.md +2 -0
- package/docs/ar/dictionary/content_file.md +24 -1
- package/docs/ar/intlayer_with_astro.md +1 -1
- package/docs/ar/intlayer_with_express.md +1 -1
- package/docs/ar/intlayer_with_nestjs.md +1 -1
- package/docs/ar/intlayer_with_next-i18next.md +1 -0
- package/docs/ar/intlayer_with_next-intl.md +1 -0
- package/docs/ar/intlayer_with_tanstack.md +122 -3
- package/docs/ar/plugins/sync-json.md +27 -2
- package/docs/de/dictionary/content_file.md +24 -1
- package/docs/de/intlayer_with_astro.md +1 -1
- package/docs/de/intlayer_with_express.md +1 -1
- package/docs/de/intlayer_with_nestjs.md +1 -1
- package/docs/de/intlayer_with_next-i18next.md +1 -0
- package/docs/de/intlayer_with_next-intl.md +1 -0
- package/docs/de/intlayer_with_tanstack.md +122 -3
- package/docs/de/plugins/sync-json.md +27 -2
- package/docs/en/dictionary/content_file.md +24 -1
- package/docs/en/intlayer_with_astro.md +1 -1
- package/docs/en/intlayer_with_express.md +1 -1
- package/docs/en/intlayer_with_nestjs.md +1 -2
- package/docs/en/intlayer_with_next-i18next.md +1 -0
- package/docs/en/intlayer_with_next-intl.md +1 -0
- package/docs/en/intlayer_with_tanstack.md +120 -1
- package/docs/en/plugins/sync-json.md +53 -2
- package/docs/en-GB/dictionary/content_file.md +24 -1
- package/docs/en-GB/intlayer_with_astro.md +1 -1
- package/docs/en-GB/intlayer_with_express.md +1 -1
- package/docs/en-GB/intlayer_with_nestjs.md +1 -1
- package/docs/en-GB/intlayer_with_next-i18next.md +1 -0
- package/docs/en-GB/intlayer_with_next-intl.md +1 -0
- package/docs/en-GB/intlayer_with_tanstack.md +121 -2
- package/docs/en-GB/plugins/sync-json.md +26 -1
- package/docs/es/dictionary/content_file.md +24 -1
- package/docs/es/intlayer_with_astro.md +1 -1
- package/docs/es/intlayer_with_express.md +1 -1
- package/docs/es/intlayer_with_nestjs.md +1 -1
- package/docs/es/intlayer_with_next-i18next.md +1 -0
- package/docs/es/intlayer_with_next-intl.md +1 -0
- package/docs/es/intlayer_with_tanstack.md +122 -3
- package/docs/es/plugins/sync-json.md +27 -2
- package/docs/fr/dictionary/content_file.md +24 -1
- package/docs/fr/intlayer_with_astro.md +1 -1
- package/docs/fr/intlayer_with_express.md +1 -1
- package/docs/fr/intlayer_with_nestjs.md +1 -1
- package/docs/fr/intlayer_with_next-i18next.md +1 -0
- package/docs/fr/intlayer_with_next-intl.md +1 -0
- package/docs/fr/intlayer_with_tanstack.md +122 -3
- package/docs/fr/plugins/sync-json.md +27 -2
- package/docs/hi/dictionary/content_file.md +24 -1
- package/docs/hi/intlayer_with_astro.md +1 -1
- package/docs/hi/intlayer_with_express.md +1 -1
- package/docs/hi/intlayer_with_nestjs.md +1 -1
- package/docs/hi/intlayer_with_next-i18next.md +1 -0
- package/docs/hi/intlayer_with_next-intl.md +1 -0
- package/docs/hi/intlayer_with_tanstack.md +122 -3
- package/docs/hi/plugins/sync-json.md +27 -2
- package/docs/id/dictionary/content_file.md +24 -1
- package/docs/id/intlayer_with_astro.md +1 -1
- package/docs/id/intlayer_with_express.md +1 -1
- package/docs/id/intlayer_with_nestjs.md +1 -1
- package/docs/id/intlayer_with_next-i18next.md +1 -0
- package/docs/id/intlayer_with_next-intl.md +1 -0
- package/docs/id/intlayer_with_tanstack.md +122 -3
- package/docs/id/plugins/sync-json.md +27 -2
- package/docs/it/dictionary/content_file.md +24 -1
- package/docs/it/intlayer_with_astro.md +1 -1
- package/docs/it/intlayer_with_express.md +1 -1
- package/docs/it/intlayer_with_nestjs.md +1 -1
- package/docs/it/intlayer_with_next-i18next.md +1 -0
- package/docs/it/intlayer_with_next-intl.md +1 -0
- package/docs/it/intlayer_with_tanstack.md +122 -3
- package/docs/it/plugins/sync-json.md +27 -2
- package/docs/ja/dictionary/content_file.md +24 -1
- package/docs/ja/intlayer_with_astro.md +1 -1
- package/docs/ja/intlayer_with_express.md +1 -1
- package/docs/ja/intlayer_with_nestjs.md +1 -1
- package/docs/ja/intlayer_with_next-i18next.md +1 -0
- package/docs/ja/intlayer_with_next-intl.md +1 -0
- package/docs/ja/intlayer_with_tanstack.md +122 -3
- package/docs/ja/plugins/sync-json.md +27 -2
- package/docs/ko/dictionary/content_file.md +44 -1
- package/docs/ko/intlayer_with_astro.md +1 -1
- package/docs/ko/intlayer_with_express.md +1 -1
- package/docs/ko/intlayer_with_nestjs.md +1 -1
- package/docs/ko/intlayer_with_next-i18next.md +1 -0
- package/docs/ko/intlayer_with_next-intl.md +1 -0
- package/docs/ko/intlayer_with_tanstack.md +122 -3
- package/docs/ko/plugins/sync-json.md +27 -2
- package/docs/pl/dictionary/content_file.md +24 -1
- package/docs/pl/intlayer_with_astro.md +2 -2
- package/docs/pl/intlayer_with_express.md +1 -1
- package/docs/pl/intlayer_with_nestjs.md +1 -1
- package/docs/pl/intlayer_with_next-i18next.md +1 -0
- package/docs/pl/intlayer_with_next-intl.md +1 -0
- package/docs/pl/intlayer_with_tanstack.md +122 -3
- package/docs/pl/plugins/sync-json.md +24 -2
- package/docs/pt/dictionary/content_file.md +24 -1
- package/docs/pt/intlayer_with_astro.md +1 -1
- package/docs/pt/intlayer_with_express.md +1 -1
- package/docs/pt/intlayer_with_nestjs.md +1 -1
- package/docs/pt/intlayer_with_next-i18next.md +1 -0
- package/docs/pt/intlayer_with_next-intl.md +1 -0
- package/docs/pt/intlayer_with_tanstack.md +122 -3
- package/docs/pt/plugins/sync-json.md +27 -2
- package/docs/ru/dictionary/content_file.md +44 -1
- package/docs/ru/intlayer_with_astro.md +1 -1
- package/docs/ru/intlayer_with_express.md +1 -1
- package/docs/ru/intlayer_with_nestjs.md +1 -1
- package/docs/ru/intlayer_with_next-i18next.md +1 -0
- package/docs/ru/intlayer_with_next-intl.md +1 -0
- package/docs/ru/intlayer_with_tanstack.md +122 -3
- package/docs/ru/plugins/sync-json.md +27 -2
- package/docs/tr/dictionary/content_file.md +44 -1
- package/docs/tr/intlayer_with_astro.md +1 -1
- package/docs/tr/intlayer_with_express.md +1 -1
- package/docs/tr/intlayer_with_next-i18next.md +1 -0
- package/docs/tr/intlayer_with_next-intl.md +1 -0
- package/docs/tr/intlayer_with_tanstack.md +122 -3
- package/docs/tr/plugins/sync-json.md +27 -2
- package/docs/vi/dictionary/content_file.md +24 -1
- package/docs/vi/intlayer_with_astro.md +1 -1
- package/docs/vi/intlayer_with_express.md +1 -1
- package/docs/vi/intlayer_with_nestjs.md +1 -1
- package/docs/vi/intlayer_with_next-i18next.md +1 -0
- package/docs/vi/intlayer_with_next-intl.md +1 -0
- package/docs/vi/intlayer_with_tanstack.md +122 -3
- package/docs/vi/plugins/sync-json.md +27 -2
- package/docs/zh/dictionary/content_file.md +44 -1
- package/docs/zh/intlayer_with_astro.md +1 -1
- package/docs/zh/intlayer_with_express.md +1 -1
- package/docs/zh/intlayer_with_nestjs.md +1 -1
- package/docs/zh/intlayer_with_next-i18next.md +1 -0
- package/docs/zh/intlayer_with_next-intl.md +1 -0
- package/docs/zh/intlayer_with_tanstack.md +122 -3
- package/docs/zh/plugins/sync-json.md +27 -2
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-03-13
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-13
|
|
4
4
|
title: مكون مزامنة JSON
|
|
5
5
|
description: مزامنة قواميس Intlayer مع ملفات JSON الخاصة بالتدويل من طرف ثالث (i18next، next-intl، react-intl، vue-i18n، والمزيد). احتفظ بنظام التدويل الحالي لديك أثناء استخدام Intlayer لإدارة وترجمة واختبار رسائلك.
|
|
6
6
|
keywords:
|
|
@@ -24,12 +24,15 @@ slugs:
|
|
|
24
24
|
- sync-json
|
|
25
25
|
youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
|
|
26
26
|
history:
|
|
27
|
+
- version: 7.5.0
|
|
28
|
+
date: 2025-12-13
|
|
29
|
+
changes: إضافة دعم تنسيقات ICU و i18next
|
|
27
30
|
- version: 6.1.6
|
|
28
31
|
date: 2025-10-05
|
|
29
32
|
changes: الوثائق الأولية لمكون مزامنة JSON
|
|
30
33
|
---
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
# مزامنة JSON (جسور التدويل) - مزامنة JSON مع دعم ICU / i18next
|
|
33
36
|
|
|
34
37
|
<iframe title="كيفية الحفاظ على مزامنة ترجمات JSON الخاصة بك مع 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&origin=http://intlayer.org&controls=0&rel=1"/>
|
|
35
38
|
|
|
@@ -105,9 +108,27 @@ syncJSON({
|
|
|
105
108
|
source: ({ key, locale }) => string, // مطلوب
|
|
106
109
|
location?: string, // تسمية اختيارية، الافتراضي: "plugin"
|
|
107
110
|
priority?: number, // أولوية اختيارية لحل التعارضات، الافتراضي: 0
|
|
111
|
+
format?: 'intlayer' | 'icu' | 'i18next', // مُنسق اختياري، الافتراضي: 'intlayer'
|
|
108
112
|
});
|
|
109
113
|
```
|
|
110
114
|
|
|
115
|
+
#### `format` ('intlayer' | 'icu' | 'i18next')
|
|
116
|
+
|
|
117
|
+
يحدد المُنسق الذي سيتم استخدامه لمحتوى القاموس عند مزامنة ملفات JSON. يسمح هذا باستخدام صيغ تنسيق رسائل مختلفة متوافقة مع مكتبات i18n مختلفة.
|
|
118
|
+
|
|
119
|
+
- `'intlayer'`: مُنسق Intlayer الافتراضي (الافتراضي).
|
|
120
|
+
- `'icu'`: يستخدم تنسيق رسائل ICU (متوافق مع مكتبات مثل react-intl، vue-i18n).
|
|
121
|
+
- `'i18next'`: يستخدم تنسيق رسائل i18next (متوافق مع i18next، next-i18next، Solid-i18next).
|
|
122
|
+
|
|
123
|
+
**مثال:**
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
syncJSON({
|
|
127
|
+
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
128
|
+
format: "i18next", // استخدام تنسيق i18next للتوافق
|
|
129
|
+
}),
|
|
130
|
+
```
|
|
131
|
+
|
|
111
132
|
## مصادر JSON متعددة والأولوية
|
|
112
133
|
|
|
113
134
|
يمكنك إضافة عدة مكونات إضافية `syncJSON` لمزامنة مصادر JSON مختلفة. هذا مفيد عندما يكون لديك مكتبات i18n متعددة أو هياكل JSON مختلفة في مشروعك.
|
|
@@ -134,6 +155,7 @@ export default defineConfig({
|
|
|
134
155
|
plugins: [
|
|
135
156
|
// المصدر الأساسي لملفات JSON (الأولوية الأعلى)
|
|
136
157
|
syncJSON({
|
|
158
|
+
format: "i18next",
|
|
137
159
|
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
138
160
|
location: "main-translations",
|
|
139
161
|
priority: 10,
|
|
@@ -141,6 +163,7 @@ export default defineConfig({
|
|
|
141
163
|
|
|
142
164
|
// المصدر الاحتياطي لملفات JSON (أولوية أقل)
|
|
143
165
|
syncJSON({
|
|
166
|
+
format: "i18next",
|
|
144
167
|
source: ({ locale }) => `./fallback-locales/${locale}.json`,
|
|
145
168
|
location: "fallback-translations",
|
|
146
169
|
priority: 5,
|
|
@@ -148,6 +171,7 @@ export default defineConfig({
|
|
|
148
171
|
|
|
149
172
|
// المصدر القديم لملفات JSON (الأولوية الأدنى)
|
|
150
173
|
syncJSON({
|
|
174
|
+
format: "i18next",
|
|
151
175
|
source: ({ locale }) => `/my/other/app/legacy/${locale}/messages.json`,
|
|
152
176
|
location: "legacy-translations",
|
|
153
177
|
priority: 1,
|
|
@@ -178,6 +202,7 @@ import { syncJSON } from "@intlayer/sync-json-plugin";
|
|
|
178
202
|
export default {
|
|
179
203
|
plugins: [
|
|
180
204
|
syncJSON({
|
|
205
|
+
format: "i18next",
|
|
181
206
|
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
182
207
|
}),
|
|
183
208
|
],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-02-07
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-13
|
|
4
4
|
title: Inhaltsdatei
|
|
5
5
|
description: Erfahren Sie, wie Sie die Erweiterungen für Ihre Inhaltsdeklarationsdateien anpassen können. Folgen Sie dieser Dokumentation, um Bedingungen effizient in Ihrem Projekt umzusetzen.
|
|
6
6
|
keywords:
|
|
@@ -12,6 +12,9 @@ slugs:
|
|
|
12
12
|
- concept
|
|
13
13
|
- content
|
|
14
14
|
history:
|
|
15
|
+
- version: 7.5.0
|
|
16
|
+
date: 2025-12-13
|
|
17
|
+
changes: Unterstützung für ICU- und i18next-Formate hinzugefügt
|
|
15
18
|
- version: 6.0.0
|
|
16
19
|
date: 2025-09-20
|
|
17
20
|
changes: Felddokumentation hinzugefügt
|
|
@@ -386,6 +389,26 @@ Array von Zeichenketten zur Kategorisierung und Organisation von Wörterbüchern
|
|
|
386
389
|
}
|
|
387
390
|
```
|
|
388
391
|
|
|
392
|
+
#### `format` ('intlayer' | 'icu' | 'i18next')
|
|
393
|
+
|
|
394
|
+
Gibt den Formatierer an, der für den Wörterbuchinhalt verwendet werden soll. Dies ermöglicht die Verwendung verschiedener Nachrichtenformatierungssyntaxen.
|
|
395
|
+
|
|
396
|
+
- `'intlayer'`: Der Standard-Intlayer-Formatierer.
|
|
397
|
+
- `'icu'`: Verwendet ICU-Nachrichtenformatierung.
|
|
398
|
+
- `'i18next'`: Verwendet i18next-Nachrichtenformatierung.
|
|
399
|
+
|
|
400
|
+
**Beispiel:**
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
{
|
|
404
|
+
key: "my-dictionary",
|
|
405
|
+
format: "icu",
|
|
406
|
+
content: {
|
|
407
|
+
message: "Hello {name}, you have {count, plural, one {# message} other {# messages}}"
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
389
412
|
#### `locale` (LocalesValues)
|
|
390
413
|
|
|
391
414
|
Wandelt das Wörterbuch in ein pro-Locale-Wörterbuch um, bei dem jedes im Inhalt deklarierte Feld automatisch in einen Übersetzungsknoten umgewandelt wird. Wenn diese Eigenschaft gesetzt ist:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
createdAt: 2024-03-07
|
|
3
3
|
updatedAt: 2025-10-03
|
|
4
4
|
title: Wie Sie Ihre Astro übersetzen – i18n-Leitfaden 2025
|
|
5
|
-
description: Erfahren Sie, wie Sie Internationalisierung (i18n) zu Ihrer
|
|
5
|
+
description: Erfahren Sie, wie Sie Internationalisierung (i18n) zu Ihrer Astro-Website mit Intlayer hinzufügen. Folgen Sie dieser Anleitung, um Ihre Website mehrsprachig zu machen.
|
|
6
6
|
keywords:
|
|
7
7
|
- Internationalisierung
|
|
8
8
|
- Dokumentation
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
createdAt: 2024-08-11
|
|
3
3
|
updatedAt: 2025-06-29
|
|
4
4
|
title: Wie Sie Ihre Express backend übersetzen – i18n-Leitfaden 2025
|
|
5
|
-
description: Entdecken Sie, wie Sie Ihre
|
|
5
|
+
description: Entdecken Sie, wie Sie Ihre Express-Backend mehrsprachig gestalten können. Befolgen Sie die Dokumentation, um sie zu internationalisieren (i18n) und zu übersetzen.
|
|
6
6
|
keywords:
|
|
7
7
|
- Internationalisierung
|
|
8
8
|
- Dokumentation
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
createdAt: 2025-09-09
|
|
3
3
|
updatedAt: 2025-09-09
|
|
4
4
|
title: Wie Sie Ihre Nest backend übersetzen – i18n-Leitfaden 2025
|
|
5
|
-
description: Entdecken Sie, wie Sie Ihr
|
|
5
|
+
description: Entdecken Sie, wie Sie Ihr NestJS-Backend mehrsprachig machen. Folgen Sie der Dokumentation, um es zu internationalisieren (i18n) und zu übersetzen.
|
|
6
6
|
keywords:
|
|
7
7
|
- Internationalisierung
|
|
8
8
|
- Dokumentation
|
|
@@ -419,6 +419,7 @@ const config: IntlayerConfig = {
|
|
|
419
419
|
plugins: [
|
|
420
420
|
// Synchronisieren Sie Ihre Ordnerstruktur pro Namespace mit Intlayer
|
|
421
421
|
syncJSON({
|
|
422
|
+
format: "icu",
|
|
422
423
|
source: ({ key, locale }) => `./locales/${locale}/${key}.json`, // Pfad zu den JSON-Übersetzungsdateien
|
|
423
424
|
}),
|
|
424
425
|
],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-09-09
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-11
|
|
4
4
|
title: Wie Sie Ihre Tanstack Start übersetzen – i18n-Leitfaden 2025
|
|
5
5
|
description: Erfahren Sie, wie Sie Internationalisierung (i18n) zu Ihrer Tanstack Start-Anwendung mit Intlayer hinzufügen. Folgen Sie dieser umfassenden Anleitung, um Ihre App mehrsprachig mit lokalisierungsbewusstem Routing zu machen.
|
|
6
6
|
keywords:
|
|
@@ -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: Füge validatePrefix hinzu und ergänze Schritt 14: 404-Seiten mit lokalisierten Routen behandeln.
|
|
22
25
|
- version: 7.3.9
|
|
23
26
|
date: 2025-12-05
|
|
24
|
-
changes:
|
|
27
|
+
changes: Füge Schritt 13 hinzu: Zugriff auf die aktuelle Locale in Serveraktionen (Optional)
|
|
25
28
|
- version: 5.8.1
|
|
26
29
|
date: 2025-09-09
|
|
27
30
|
changes: Hinzugefügt für Tanstack Start
|
|
@@ -614,7 +617,123 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
614
617
|
|
|
615
618
|
---
|
|
616
619
|
|
|
617
|
-
### Schritt 14:
|
|
620
|
+
### Schritt 14: Nicht gefundene Seiten verwalten (optional)
|
|
621
|
+
|
|
622
|
+
Wenn ein Benutzer eine nicht existierende Seite besucht, können Sie eine benutzerdefinierte Seite "Nicht gefunden" anzeigen, und das Locale-Präfix kann beeinflussen, wie die Seite "Nicht gefunden" ausgelöst wird.
|
|
623
|
+
|
|
624
|
+
#### Verstehen der 404-Behandlung von TanStack Router mit Locale-Präfixen
|
|
625
|
+
|
|
626
|
+
In TanStack Router erfordert die Behandlung von 404-Seiten mit lokalisierten Routen einen mehrschichtigen Ansatz:
|
|
627
|
+
|
|
628
|
+
1. **Dedizierte 404-Route**: Eine spezifische Route zur Anzeige der 404-Benutzeroberfläche
|
|
629
|
+
2. **Validierung auf Routenebene**: Validiert Locale-Präfixe und leitet ungültige zu 404 weiter
|
|
630
|
+
3. **Catch-all-Route**: Erfasst alle nicht übereinstimmenden Pfade innerhalb des Locale-Segments
|
|
631
|
+
|
|
632
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
633
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
634
|
+
|
|
635
|
+
// Dies erstellt eine dedizierte /[locale]/404 Route
|
|
636
|
+
// Sie wird sowohl als direkte Route verwendet als auch als Komponente in anderen Dateien importiert
|
|
637
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
638
|
+
component: NotFoundComponent,
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// Separately exportiert, damit es in notFoundComponent und catch-all Routen wiederverwendet werden kann
|
|
642
|
+
export function NotFoundComponent() {
|
|
643
|
+
return (
|
|
644
|
+
<div>
|
|
645
|
+
<h1>404</h1>
|
|
646
|
+
</div>
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
652
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
653
|
+
import { validatePrefix } from "intlayer";
|
|
654
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
655
|
+
|
|
656
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
657
|
+
import { NotFoundComponent } from "./404";
|
|
658
|
+
|
|
659
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
660
|
+
// beforeLoad läuft, bevor die Route gerendert wird (sowohl auf Server als auch Client)
|
|
661
|
+
// Es ist der ideale Ort, um das Locale-Präfix zu validieren
|
|
662
|
+
beforeLoad: ({ params }) => {
|
|
663
|
+
// Locale aus Routenparametern abrufen (nicht aus Server-Headern, da beforeLoad sowohl auf Client als auch Server läuft)
|
|
664
|
+
const localeParam = params.locale;
|
|
665
|
+
|
|
666
|
+
// validatePrefix prüft, ob die Locale gemäß Ihrer intlayer-Konfiguration gültig ist
|
|
667
|
+
// Gibt zurück: { isValid: boolean, localePrefix: string }
|
|
668
|
+
// - isValid: true, wenn das Präfix mit einer konfigurierten Locale übereinstimmt (oder leer ist, wenn das Präfix optional ist)
|
|
669
|
+
// - localePrefix: das validierte Präfix oder das Standard-Locale-Präfix für Umleitungen
|
|
670
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
671
|
+
|
|
672
|
+
if (isValid) {
|
|
673
|
+
// Locale ist gültig, Route normal rendern lassen
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// Ungültiges Locale-Präfix (z. B. /xyz/about, wobei "xyz" keine gültige Locale ist)
|
|
678
|
+
// Zur 404-Seite mit einem gültigen Locale-Präfix umleiten
|
|
679
|
+
// Dies stellt sicher, dass die 404-Seite weiterhin korrekt lokalisiert ist
|
|
680
|
+
throw redirect({
|
|
681
|
+
to: "/{-$locale}/404",
|
|
682
|
+
params: { locale: localePrefix },
|
|
683
|
+
});
|
|
684
|
+
},
|
|
685
|
+
component: RouteComponent,
|
|
686
|
+
// notFoundComponent wird aufgerufen, wenn eine untergeordnete Route nicht existiert
|
|
687
|
+
// z. B. löst /en/nicht-vorhandene-seite dies innerhalb des /en-Layouts aus
|
|
688
|
+
notFoundComponent: NotFoundLayout,
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
function RouteComponent() {
|
|
692
|
+
const { defaultLocale } = useLocale();
|
|
693
|
+
const { locale } = Route.useParams();
|
|
694
|
+
|
|
695
|
+
return (
|
|
696
|
+
// Den gesamten Locale-Segment mit IntlayerProvider umschließen
|
|
697
|
+
// Fällt auf defaultLocale zurück, wenn der locale-Parameter undefined ist (optionaler Präfix-Modus)
|
|
698
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
699
|
+
<Outlet />
|
|
700
|
+
</IntlayerProvider>
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// NotFoundLayout umschließt die 404-Komponente mit IntlayerProvider
|
|
705
|
+
// Dies stellt sicher, dass Übersetzungen auf der 404-Seite weiterhin funktionieren
|
|
706
|
+
function NotFoundLayout() {
|
|
707
|
+
const { defaultLocale } = useLocale();
|
|
708
|
+
const { locale } = Route.useParams();
|
|
709
|
+
|
|
710
|
+
return (
|
|
711
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
712
|
+
<NotFoundComponent />
|
|
713
|
+
{/* LocaleSwitcher einbinden, damit Benutzer die Sprache auch auf 404 ändern können */}
|
|
714
|
+
<LocaleSwitcher />
|
|
715
|
+
</IntlayerProvider>
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
721
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
722
|
+
|
|
723
|
+
import { NotFoundComponent } from "./404";
|
|
724
|
+
|
|
725
|
+
// Die $ (splat/catch-all) Route passt auf jeden Pfad, der nicht mit anderen Routen übereinstimmt
|
|
726
|
+
// z. B. /en/irgendein/tief/verschachtelter/ungültiger/pfad
|
|
727
|
+
// Dies stellt sicher, dass ALLE nicht übereinstimmenden Pfade innerhalb einer Locale die 404-Seite anzeigen
|
|
728
|
+
// Ohne dies könnten nicht übereinstimmende tiefe Pfade eine leere Seite oder einen Fehler anzeigen
|
|
729
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
730
|
+
component: NotFoundComponent,
|
|
731
|
+
});
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
### Schritt 15: TypeScript konfigurieren (optional)
|
|
618
737
|
|
|
619
738
|
Intlayer verwendet Module Augmentation, um die Vorteile von TypeScript zu nutzen und Ihren Code robuster zu machen.
|
|
620
739
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-03-13
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-13
|
|
4
4
|
title: Sync JSON Plugin
|
|
5
5
|
description: Synchronisieren Sie Intlayer-Wörterbücher mit Drittanbieter-i18n-JSON-Dateien (i18next, next-intl, react-intl, vue-i18n und mehr). Behalten Sie Ihr bestehendes i18n bei und verwenden Sie Intlayer, um Ihre Nachrichten zu verwalten, zu übersetzen und zu testen.
|
|
6
6
|
keywords:
|
|
@@ -24,12 +24,15 @@ slugs:
|
|
|
24
24
|
- sync-json
|
|
25
25
|
youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
|
|
26
26
|
history:
|
|
27
|
+
- version: 7.5.0
|
|
28
|
+
date: 2025-12-13
|
|
29
|
+
changes: Unterstützung für ICU- und i18next-Formate hinzugefügt
|
|
27
30
|
- version: 6.1.6
|
|
28
31
|
date: 2025-10-05
|
|
29
32
|
changes: Erste Dokumentation des Sync JSON Plugins
|
|
30
33
|
---
|
|
31
34
|
|
|
32
|
-
# Sync JSON (i18n-Brücken)
|
|
35
|
+
# Sync JSON (i18n-Brücken) - Sync JSON mit ICU / i18next-Unterstützung
|
|
33
36
|
|
|
34
37
|
<iframe title="Wie Sie Ihre JSON-Übersetzungen mit Intlayer synchronisiert halten" 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&origin=http://intlayer.org&controls=0&rel=1"/>
|
|
35
38
|
|
|
@@ -105,9 +108,27 @@ syncJSON({
|
|
|
105
108
|
source: ({ key, locale }) => string, // erforderlich
|
|
106
109
|
location?: string, // optionales Label, Standard: "plugin"
|
|
107
110
|
priority?: number, // optionale Priorität zur Konfliktlösung, Standard: 0
|
|
111
|
+
format?: 'intlayer' | 'icu' | 'i18next', // optionaler Formatierer, Standard: 'intlayer'
|
|
108
112
|
});
|
|
109
113
|
```
|
|
110
114
|
|
|
115
|
+
#### `format` ('intlayer' | 'icu' | 'i18next')
|
|
116
|
+
|
|
117
|
+
Gibt den Formatierer an, der für den Wörterbuchinhalt bei der Synchronisierung von JSON-Dateien verwendet werden soll. Dies ermöglicht die Verwendung verschiedener Nachrichtenformatierungssyntaxen, die mit verschiedenen i18n-Bibliotheken kompatibel sind.
|
|
118
|
+
|
|
119
|
+
- `'intlayer'`: Der Standard-Intlayer-Formatierer (Standard).
|
|
120
|
+
- `'icu'`: Verwendet ICU-Nachrichtenformatierung (kompatibel mit Bibliotheken wie react-intl, vue-i18n).
|
|
121
|
+
- `'i18next'`: Verwendet i18next-Nachrichtenformatierung (kompatibel mit i18next, next-i18next, Solid-i18next).
|
|
122
|
+
|
|
123
|
+
**Beispiel:**
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
syncJSON({
|
|
127
|
+
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
128
|
+
format: "i18next", // i18next-Formatierung für Kompatibilität verwenden
|
|
129
|
+
}),
|
|
130
|
+
```
|
|
131
|
+
|
|
111
132
|
## Mehrere JSON-Quellen und Priorität
|
|
112
133
|
|
|
113
134
|
Sie können mehrere `syncJSON`-Plugins hinzufügen, um verschiedene JSON-Quellen zu synchronisieren. Dies ist nützlich, wenn Sie mehrere i18n-Bibliotheken oder unterschiedliche JSON-Strukturen in Ihrem Projekt haben.
|
|
@@ -134,6 +155,7 @@ export default defineConfig({
|
|
|
134
155
|
plugins: [
|
|
135
156
|
// Primäre JSON-Quelle (höchste Priorität)
|
|
136
157
|
syncJSON({
|
|
158
|
+
format: "i18next",
|
|
137
159
|
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
138
160
|
location: "main-translations",
|
|
139
161
|
priority: 10,
|
|
@@ -141,6 +163,7 @@ export default defineConfig({
|
|
|
141
163
|
|
|
142
164
|
// Fallback-JSON-Quelle (niedrigere Priorität)
|
|
143
165
|
syncJSON({
|
|
166
|
+
format: "i18next",
|
|
144
167
|
source: ({ locale }) => `./fallback-locales/${locale}.json`,
|
|
145
168
|
location: "fallback-translations",
|
|
146
169
|
priority: 5,
|
|
@@ -148,6 +171,7 @@ export default defineConfig({
|
|
|
148
171
|
|
|
149
172
|
// Legacy-JSON-Quelle (niedrigste Priorität)
|
|
150
173
|
syncJSON({
|
|
174
|
+
format: "i18next",
|
|
151
175
|
source: ({ locale }) => `/my/other/app/legacy/${locale}/messages.json`,
|
|
152
176
|
location: "legacy-translations",
|
|
153
177
|
priority: 1,
|
|
@@ -178,6 +202,7 @@ import { syncJSON } from "@intlayer/sync-json-plugin";
|
|
|
178
202
|
export default {
|
|
179
203
|
plugins: [
|
|
180
204
|
syncJSON({
|
|
205
|
+
format: "i18next",
|
|
181
206
|
source: ({ key, locale }) => `./locales/${locale}/${key}.json`,
|
|
182
207
|
}),
|
|
183
208
|
],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-02-07
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-13
|
|
4
4
|
title: Content File
|
|
5
5
|
description: Learn how to customize the extensions for your content declaration files. Follow this documentation to implement conditions efficiently in your project.
|
|
6
6
|
keywords:
|
|
@@ -12,6 +12,9 @@ slugs:
|
|
|
12
12
|
- concept
|
|
13
13
|
- content
|
|
14
14
|
history:
|
|
15
|
+
- version: 7.5.0
|
|
16
|
+
date: 2025-12-13
|
|
17
|
+
changes: Add ICU and i18next format support
|
|
15
18
|
- version: 7.0.0
|
|
16
19
|
date: 2025-10-23
|
|
17
20
|
changes: Rename `autoFill` to `fill`
|
|
@@ -387,6 +390,26 @@ Array of strings for categorizing and organizing dictionaries. Tags provide addi
|
|
|
387
390
|
}
|
|
388
391
|
```
|
|
389
392
|
|
|
393
|
+
#### `format` ('intlayer' | 'icu' | 'i18next')
|
|
394
|
+
|
|
395
|
+
Specifies the formatter to use for the dictionary content. This allows using different message formatting syntaxes.
|
|
396
|
+
|
|
397
|
+
- `'intlayer'`: The default Intlayer formatter.
|
|
398
|
+
- `'icu'`: Uses ICU message formatting.
|
|
399
|
+
- `'i18next'`: Uses i18next message formatting.
|
|
400
|
+
|
|
401
|
+
**Example:**
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
{
|
|
405
|
+
key: "my-dictionary",
|
|
406
|
+
format: "icu",
|
|
407
|
+
content: {
|
|
408
|
+
message: "Hello {name}, you have {count, plural, one {# message} other {# messages}}"
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
390
413
|
#### `locale` (LocalesValues)
|
|
391
414
|
|
|
392
415
|
Transforms the dictionary into a per-locale dictionary where each field declared in the content will be automatically transformed into a translation node. When this property is set:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
createdAt: 2024-03-07
|
|
3
3
|
updatedAt: 2025-10-03
|
|
4
4
|
title: How to translate your Astro app – i18n guide 2025
|
|
5
|
-
description: Learn how to add internationalization (i18n) to your
|
|
5
|
+
description: Learn how to add internationalization (i18n) to your Astro website using Intlayer. Follow this guide to make your site multilingual.
|
|
6
6
|
keywords:
|
|
7
7
|
- Internationalization
|
|
8
8
|
- Documentation
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
createdAt: 2025-08-23
|
|
3
3
|
updatedAt: 2025-08-23
|
|
4
4
|
title: How to translate your Express backend – i18n guide 2025
|
|
5
|
-
description: Discover how to make your
|
|
5
|
+
description: Discover how to make your Express backend multilingual. Follow the documentation to internationalize (i18n) and translate it.
|
|
6
6
|
keywords:
|
|
7
7
|
- Internationalization
|
|
8
8
|
- Documentation
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
createdAt: 2025-09-09
|
|
3
3
|
updatedAt: 2025-09-09
|
|
4
4
|
title: How to translate your Nest backend – i18n guide 2025
|
|
5
|
-
description: Discover how to make your
|
|
5
|
+
description: Discover how to make your NestJS backend multilingual. Follow the documentation to internationalize (i18n) and translate it.
|
|
6
6
|
keywords:
|
|
7
7
|
- Internationalization
|
|
8
8
|
- Documentation
|
|
@@ -15,7 +15,6 @@ slugs:
|
|
|
15
15
|
- environment
|
|
16
16
|
- nest
|
|
17
17
|
applicationTemplate: https://github.com/AydinTheFirst/nestjs-intlayer
|
|
18
|
-
author: AydinTheFirst
|
|
19
18
|
history:
|
|
20
19
|
- version: 5.8.0
|
|
21
20
|
date: 2025-09-09
|
|
@@ -19,6 +19,9 @@ 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: Introduce validatePrefix and add step 14: Handling 404 pages with localized routes.
|
|
22
25
|
- version: 7.3.9
|
|
23
26
|
date: 2025-12-05
|
|
24
27
|
changes: Add step 13: Retrieve the locale in your server actions (Optional)
|
|
@@ -611,7 +614,123 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
611
614
|
|
|
612
615
|
---
|
|
613
616
|
|
|
614
|
-
### Step 14:
|
|
617
|
+
### Step 14: Manage not found pages (Optional)
|
|
618
|
+
|
|
619
|
+
When a user visits a non-existing page, you can display a custom not found page and the locale prefix may impact the way the not found page is triggered.
|
|
620
|
+
|
|
621
|
+
#### Understanding TanStack Router's 404 Handling with Locale Prefixes
|
|
622
|
+
|
|
623
|
+
In TanStack Router, handling 404 pages with localized routes requires a multi-layered approach:
|
|
624
|
+
|
|
625
|
+
1. **Dedicated 404 route**: A specific route to display the 404 UI
|
|
626
|
+
2. **Route-level validation**: Validates locale prefixes and redirects invalid ones to 404
|
|
627
|
+
3. **Catch-all route**: Captures any unmatched paths within the locale segment
|
|
628
|
+
|
|
629
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
630
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
631
|
+
|
|
632
|
+
// This creates a dedicated /[locale]/404 route
|
|
633
|
+
// It's used both as a direct route and imported as a component in other files
|
|
634
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
635
|
+
component: NotFoundComponent,
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
// Exported separately so it can be reused in notFoundComponent and catch-all routes
|
|
639
|
+
export function NotFoundComponent() {
|
|
640
|
+
return (
|
|
641
|
+
<div>
|
|
642
|
+
<h1>404</h1>
|
|
643
|
+
</div>
|
|
644
|
+
);
|
|
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 runs before the route renders (on both server and client)
|
|
658
|
+
// It's the ideal place to validate the locale prefix
|
|
659
|
+
beforeLoad: ({ params }) => {
|
|
660
|
+
// Get locale from route params (not from server headers, as beforeLoad runs on both client and server)
|
|
661
|
+
const localeParam = params.locale;
|
|
662
|
+
|
|
663
|
+
// validatePrefix checks if the locale is valid according to your intlayer config
|
|
664
|
+
// Returns: { isValid: boolean, localePrefix: string }
|
|
665
|
+
// - isValid: true if the prefix matches a configured locale (or is empty when prefix is optional)
|
|
666
|
+
// - localePrefix: the validated prefix or the default locale prefix for redirects
|
|
667
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
668
|
+
|
|
669
|
+
if (isValid) {
|
|
670
|
+
// Locale is valid, allow the route to render normally
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Invalid locale prefix (e.g., /xyz/about where "xyz" isn't a valid locale)
|
|
675
|
+
// Redirect to the 404 page with a valid locale prefix
|
|
676
|
+
// This ensures the 404 page is still properly localized
|
|
677
|
+
throw redirect({
|
|
678
|
+
to: "/{-$locale}/404",
|
|
679
|
+
params: { locale: localePrefix },
|
|
680
|
+
});
|
|
681
|
+
},
|
|
682
|
+
component: RouteComponent,
|
|
683
|
+
// notFoundComponent is called when a child route doesn't exist
|
|
684
|
+
// e.g., /en/non-existent-page triggers this within the /en layout
|
|
685
|
+
notFoundComponent: NotFoundLayout,
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
function RouteComponent() {
|
|
689
|
+
const { defaultLocale } = useLocale();
|
|
690
|
+
const { locale } = Route.useParams();
|
|
691
|
+
|
|
692
|
+
return (
|
|
693
|
+
// Wrap the entire locale segment with IntlayerProvider
|
|
694
|
+
// Falls back to defaultLocale when locale param is undefined (optional prefix mode)
|
|
695
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
696
|
+
<Outlet />
|
|
697
|
+
</IntlayerProvider>
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// NotFoundLayout wraps the 404 component with IntlayerProvider
|
|
702
|
+
// This ensures translations still work on the 404 page
|
|
703
|
+
function NotFoundLayout() {
|
|
704
|
+
const { defaultLocale } = useLocale();
|
|
705
|
+
const { locale } = Route.useParams();
|
|
706
|
+
|
|
707
|
+
return (
|
|
708
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
709
|
+
<NotFoundComponent />
|
|
710
|
+
{/* Include LocaleSwitcher so users can change language even on 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
|
+
// The $ (splat/catch-all) route matches any path that doesn't match other routes
|
|
723
|
+
// e.g., /en/some/deeply/nested/invalid/path
|
|
724
|
+
// This ensures ALL unmatched paths within a locale show the 404 page
|
|
725
|
+
// Without this, unmatched deep paths might show a blank page or error
|
|
726
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
727
|
+
component: NotFoundComponent,
|
|
728
|
+
});
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
### Step 15: Configure TypeScript (Optional)
|
|
615
734
|
|
|
616
735
|
Intlayer uses module augmentation to get benefits of TypeScript and make your codebase stronger.
|
|
617
736
|
|