@intlayer/docs 7.3.15 → 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.
- package/docs/ar/intlayer_with_tanstack.md +132 -2
- package/docs/de/intlayer_with_tanstack.md +132 -2
- package/docs/en/intlayer_with_tanstack.md +131 -1
- package/docs/en-GB/intlayer_with_tanstack.md +131 -1
- package/docs/es/intlayer_with_tanstack.md +132 -2
- package/docs/fr/intlayer_with_tanstack.md +132 -2
- package/docs/hi/intlayer_with_tanstack.md +132 -2
- package/docs/id/intlayer_with_tanstack.md +132 -2
- package/docs/it/intlayer_with_tanstack.md +132 -2
- package/docs/ja/intlayer_with_tanstack.md +132 -2
- package/docs/ko/intlayer_with_tanstack.md +132 -2
- package/docs/pl/intlayer_with_tanstack.md +132 -2
- package/docs/pt/intlayer_with_tanstack.md +132 -2
- package/docs/ru/intlayer_with_tanstack.md +132 -2
- package/docs/tr/intlayer_with_tanstack.md +132 -2
- package/docs/vi/intlayer_with_tanstack.md +132 -2
- package/docs/zh/intlayer_with_tanstack.md +132 -2
- package/package.json +6 -6
|
@@ -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:
|
|
27
|
+
changes: أضف خطوة 13: كيفية جلب اللغة الحالية داخل عمليات الخادم (اختياري)
|
|
25
28
|
- version: 5.8.1
|
|
26
29
|
date: 2025-09-09
|
|
27
30
|
changes: أضيف لـ Tanstack Start
|
|
@@ -599,7 +602,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
599
602
|
|
|
600
603
|
---
|
|
601
604
|
|
|
602
|
-
### الخطوة 14:
|
|
605
|
+
### الخطوة 14: إدارة الصفحات غير الموجودة (اختياري)
|
|
606
|
+
|
|
607
|
+
عندما يزور المستخدم صفحة غير موجودة، يمكنك عرض صفحة مخصصة "غير موجودة" وقد يؤثر بادئة اللغة على طريقة تشغيل صفحة "غير موجودة".
|
|
608
|
+
|
|
609
|
+
#### فهم معالجة 404 في TanStack Router مع بادئات اللغة
|
|
610
|
+
|
|
611
|
+
في TanStack Router، يتطلب التعامل مع صفحات 404 باستخدام المسارات المترجمة نهجًا متعدد الطبقات:
|
|
612
|
+
|
|
613
|
+
1. **مسار 404 مخصص**: مسار محدد لعرض واجهة المستخدم 404
|
|
614
|
+
2. **التحقق على مستوى المسار**: يتحقق من بادئات اللغة ويعيد توجيه غير الصالحة إلى 404
|
|
615
|
+
3. **مسار catch-all**: يلتقط أي مسارات غير متطابقة داخل مقطع اللغة
|
|
616
|
+
|
|
617
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
618
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
619
|
+
|
|
620
|
+
// هذا ينشئ مسارًا مخصصًا /[locale]/404
|
|
621
|
+
// يتم استخدامه كمسار مباشر واستيراده كعنصر في ملفات أخرى
|
|
622
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
623
|
+
component: NotFoundComponent,
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
// يتم تصديره بشكل منفصل حتى يمكن إعادة استخدامه في notFoundComponent والمسارات catch-all
|
|
627
|
+
export function NotFoundComponent() {
|
|
628
|
+
return (
|
|
629
|
+
<div>
|
|
630
|
+
<h1>404</h1>
|
|
631
|
+
</div>
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
637
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
638
|
+
|
|
639
|
+
// المسار الجذري يعمل كتخطيط على المستوى الأعلى
|
|
640
|
+
// لا يتعامل مع 404 مباشرة - يتم تفويض ذلك إلى المسارات الفرعية
|
|
641
|
+
// هذا يحافظ على الجذر بسيطًا ويتيح للمسارات الواعية باللغة إدارة منطق 404 الخاص بها
|
|
642
|
+
export const Route = createRootRoute({
|
|
643
|
+
component: Outlet,
|
|
644
|
+
});
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
648
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
649
|
+
import { validatePrefix } from "intlayer";
|
|
650
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
651
|
+
|
|
652
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
653
|
+
import { NotFoundComponent } from "./404";
|
|
654
|
+
|
|
655
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
656
|
+
// beforeLoad يعمل قبل عرض المسار (على كل من الخادم والعميل)
|
|
657
|
+
// إنه المكان المثالي للتحقق من بادئة اللغة
|
|
658
|
+
beforeLoad: ({ params }) => {
|
|
659
|
+
// الحصول على اللغة من معاملات المسار (وليس من رؤوس الخادم، حيث يعمل beforeLoad على كل من العميل والخادم)
|
|
660
|
+
const localeParam = params.locale;
|
|
661
|
+
|
|
662
|
+
// validatePrefix يتحقق مما إذا كانت اللغة صالحة وفقًا لتكوين intlayer الخاص بك
|
|
663
|
+
// إرجاع: { isValid: boolean, localePrefix: string }
|
|
664
|
+
// - isValid: true إذا كانت البادئة تطابق لغة مُكوَّنة (أو فارغة عندما تكون البادئة اختيارية)
|
|
665
|
+
// - localePrefix: البادئة المُتحقق منها أو بادئة اللغة الافتراضية لإعادة التوجيه
|
|
666
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
667
|
+
|
|
668
|
+
if (isValid) {
|
|
669
|
+
// اللغة صالحة، السماح للمسار بالعرض بشكل طبيعي
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// بادئة لغة غير صالحة (على سبيل المثال، /xyz/about حيث "xyz" ليست لغة صالحة)
|
|
674
|
+
// إعادة التوجيه إلى صفحة 404 ببادئة لغة صالحة
|
|
675
|
+
// يضمن هذا أن صفحة 404 لا تزال محلية بشكل صحيح
|
|
676
|
+
throw redirect({
|
|
677
|
+
to: "/{-$locale}/404",
|
|
678
|
+
params: { locale: localePrefix },
|
|
679
|
+
});
|
|
680
|
+
},
|
|
681
|
+
component: RouteComponent,
|
|
682
|
+
// يتم استدعاء notFoundComponent عندما لا يوجد مسار فرعي
|
|
683
|
+
// على سبيل المثال، /en/صفحة-غير-موجودة يطلق هذا داخل تخطيط /en
|
|
684
|
+
notFoundComponent: NotFoundLayout,
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
function RouteComponent() {
|
|
688
|
+
const { defaultLocale } = useLocale();
|
|
689
|
+
const { locale } = Route.useParams();
|
|
690
|
+
|
|
691
|
+
return (
|
|
692
|
+
// لف كامل مقطع اللغة بـ IntlayerProvider
|
|
693
|
+
// يعود إلى defaultLocale عندما تكون معلمة اللغة undefined (وضع البادئة الاختياري)
|
|
694
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
695
|
+
<Outlet />
|
|
696
|
+
</IntlayerProvider>
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
// NotFoundLayout يلف عنصر 404 بـ IntlayerProvider
|
|
701
|
+
// يضمن هذا أن الترجمات لا تزال تعمل على صفحة 404
|
|
702
|
+
function NotFoundLayout() {
|
|
703
|
+
const { defaultLocale } = useLocale();
|
|
704
|
+
const { locale } = Route.useParams();
|
|
705
|
+
|
|
706
|
+
return (
|
|
707
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
708
|
+
<NotFoundComponent />
|
|
709
|
+
{/* تضمين LocaleSwitcher حتى يتمكن المستخدمون من تغيير اللغة حتى على 404 */}
|
|
710
|
+
<LocaleSwitcher />
|
|
711
|
+
</IntlayerProvider>
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
717
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
718
|
+
|
|
719
|
+
import { NotFoundComponent } from "./404";
|
|
720
|
+
|
|
721
|
+
// المسار $ (splat/catch-all) يطابق أي مسار لا يطابق المسارات الأخرى
|
|
722
|
+
// على سبيل المثال، /en/بعض/المسار/المتداخل/بعمق/غير-صالح
|
|
723
|
+
// يضمن هذا أن جميع المسارات غير المتطابقة داخل اللغة تعرض صفحة 404
|
|
724
|
+
// بدون هذا، قد تعرض المسارات العميقة غير المتطابقة صفحة فارغة أو خطأ
|
|
725
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
726
|
+
component: NotFoundComponent,
|
|
727
|
+
});
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
---
|
|
731
|
+
|
|
732
|
+
### الخطوة 15: تكوين TypeScript (اختياري)
|
|
603
733
|
|
|
604
734
|
يستخدم Intlayer توسيع الوحدات (module augmentation) للاستفادة من TypeScript وجعل قاعدة الشيفرة الخاصة بك أقوى.
|
|
605
735
|
|
|
@@ -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,134 @@ 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/__root.tsx"
|
|
652
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
653
|
+
|
|
654
|
+
// Die Root-Route dient als Layout auf oberster Ebene
|
|
655
|
+
// Sie behandelt 404s nicht direkt - das wird an untergeordnete Routen delegiert
|
|
656
|
+
// Dies hält die Root einfach und ermöglicht es locale-bewussten Routen, ihre eigene 404-Logik zu verwalten
|
|
657
|
+
export const Route = createRootRoute({
|
|
658
|
+
component: Outlet,
|
|
659
|
+
});
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
663
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
664
|
+
import { validatePrefix } from "intlayer";
|
|
665
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
666
|
+
|
|
667
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
668
|
+
import { NotFoundComponent } from "./404";
|
|
669
|
+
|
|
670
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
671
|
+
// beforeLoad läuft, bevor die Route gerendert wird (sowohl auf Server als auch Client)
|
|
672
|
+
// Es ist der ideale Ort, um das Locale-Präfix zu validieren
|
|
673
|
+
beforeLoad: ({ params }) => {
|
|
674
|
+
// Locale aus Routenparametern abrufen (nicht aus Server-Headern, da beforeLoad sowohl auf Client als auch Server läuft)
|
|
675
|
+
const localeParam = params.locale;
|
|
676
|
+
|
|
677
|
+
// validatePrefix prüft, ob die Locale gemäß Ihrer intlayer-Konfiguration gültig ist
|
|
678
|
+
// Gibt zurück: { isValid: boolean, localePrefix: string }
|
|
679
|
+
// - isValid: true, wenn das Präfix mit einer konfigurierten Locale übereinstimmt (oder leer ist, wenn das Präfix optional ist)
|
|
680
|
+
// - localePrefix: das validierte Präfix oder das Standard-Locale-Präfix für Umleitungen
|
|
681
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
682
|
+
|
|
683
|
+
if (isValid) {
|
|
684
|
+
// Locale ist gültig, Route normal rendern lassen
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Ungültiges Locale-Präfix (z. B. /xyz/about, wobei "xyz" keine gültige Locale ist)
|
|
689
|
+
// Zur 404-Seite mit einem gültigen Locale-Präfix umleiten
|
|
690
|
+
// Dies stellt sicher, dass die 404-Seite weiterhin korrekt lokalisiert ist
|
|
691
|
+
throw redirect({
|
|
692
|
+
to: "/{-$locale}/404",
|
|
693
|
+
params: { locale: localePrefix },
|
|
694
|
+
});
|
|
695
|
+
},
|
|
696
|
+
component: RouteComponent,
|
|
697
|
+
// notFoundComponent wird aufgerufen, wenn eine untergeordnete Route nicht existiert
|
|
698
|
+
// z. B. löst /en/nicht-vorhandene-seite dies innerhalb des /en-Layouts aus
|
|
699
|
+
notFoundComponent: NotFoundLayout,
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
function RouteComponent() {
|
|
703
|
+
const { defaultLocale } = useLocale();
|
|
704
|
+
const { locale } = Route.useParams();
|
|
705
|
+
|
|
706
|
+
return (
|
|
707
|
+
// Den gesamten Locale-Segment mit IntlayerProvider umschließen
|
|
708
|
+
// Fällt auf defaultLocale zurück, wenn der locale-Parameter undefined ist (optionaler Präfix-Modus)
|
|
709
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
710
|
+
<Outlet />
|
|
711
|
+
</IntlayerProvider>
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
// NotFoundLayout umschließt die 404-Komponente mit IntlayerProvider
|
|
716
|
+
// Dies stellt sicher, dass Übersetzungen auf der 404-Seite weiterhin funktionieren
|
|
717
|
+
function NotFoundLayout() {
|
|
718
|
+
const { defaultLocale } = useLocale();
|
|
719
|
+
const { locale } = Route.useParams();
|
|
720
|
+
|
|
721
|
+
return (
|
|
722
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
723
|
+
<NotFoundComponent />
|
|
724
|
+
{/* LocaleSwitcher einbinden, damit Benutzer die Sprache auch auf 404 ändern können */}
|
|
725
|
+
<LocaleSwitcher />
|
|
726
|
+
</IntlayerProvider>
|
|
727
|
+
);
|
|
728
|
+
}
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
732
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
733
|
+
|
|
734
|
+
import { NotFoundComponent } from "./404";
|
|
735
|
+
|
|
736
|
+
// Die $ (splat/catch-all) Route passt auf jeden Pfad, der nicht mit anderen Routen übereinstimmt
|
|
737
|
+
// z. B. /en/irgendein/tief/verschachtelter/ungültiger/pfad
|
|
738
|
+
// Dies stellt sicher, dass ALLE nicht übereinstimmenden Pfade innerhalb einer Locale die 404-Seite anzeigen
|
|
739
|
+
// Ohne dies könnten nicht übereinstimmende tiefe Pfade eine leere Seite oder einen Fehler anzeigen
|
|
740
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
741
|
+
component: NotFoundComponent,
|
|
742
|
+
});
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
---
|
|
746
|
+
|
|
747
|
+
### Schritt 15: TypeScript konfigurieren (optional)
|
|
618
748
|
|
|
619
749
|
Intlayer verwendet Module Augmentation, um die Vorteile von TypeScript zu nutzen und Ihren Code robuster zu machen.
|
|
620
750
|
|
|
@@ -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,134 @@ 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/__root.tsx"
|
|
649
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
650
|
+
|
|
651
|
+
// The root route serves as the top-level layout
|
|
652
|
+
// It doesn't handle 404s directly - that's delegated to child routes
|
|
653
|
+
// This keeps the root simple and lets locale-aware routes manage their own 404 logic
|
|
654
|
+
export const Route = createRootRoute({
|
|
655
|
+
component: Outlet,
|
|
656
|
+
});
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
660
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
661
|
+
import { validatePrefix } from "intlayer";
|
|
662
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
663
|
+
|
|
664
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
665
|
+
import { NotFoundComponent } from "./404";
|
|
666
|
+
|
|
667
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
668
|
+
// beforeLoad runs before the route renders (on both server and client)
|
|
669
|
+
// It's the ideal place to validate the locale prefix
|
|
670
|
+
beforeLoad: ({ params }) => {
|
|
671
|
+
// Get locale from route params (not from server headers, as beforeLoad runs on both client and server)
|
|
672
|
+
const localeParam = params.locale;
|
|
673
|
+
|
|
674
|
+
// validatePrefix checks if the locale is valid according to your intlayer config
|
|
675
|
+
// Returns: { isValid: boolean, localePrefix: string }
|
|
676
|
+
// - isValid: true if the prefix matches a configured locale (or is empty when prefix is optional)
|
|
677
|
+
// - localePrefix: the validated prefix or the default locale prefix for redirects
|
|
678
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
679
|
+
|
|
680
|
+
if (isValid) {
|
|
681
|
+
// Locale is valid, allow the route to render normally
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// Invalid locale prefix (e.g., /xyz/about where "xyz" isn't a valid locale)
|
|
686
|
+
// Redirect to the 404 page with a valid locale prefix
|
|
687
|
+
// This ensures the 404 page is still properly localized
|
|
688
|
+
throw redirect({
|
|
689
|
+
to: "/{-$locale}/404",
|
|
690
|
+
params: { locale: localePrefix },
|
|
691
|
+
});
|
|
692
|
+
},
|
|
693
|
+
component: RouteComponent,
|
|
694
|
+
// notFoundComponent is called when a child route doesn't exist
|
|
695
|
+
// e.g., /en/non-existent-page triggers this within the /en layout
|
|
696
|
+
notFoundComponent: NotFoundLayout,
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
function RouteComponent() {
|
|
700
|
+
const { defaultLocale } = useLocale();
|
|
701
|
+
const { locale } = Route.useParams();
|
|
702
|
+
|
|
703
|
+
return (
|
|
704
|
+
// Wrap the entire locale segment with IntlayerProvider
|
|
705
|
+
// Falls back to defaultLocale when locale param is undefined (optional prefix mode)
|
|
706
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
707
|
+
<Outlet />
|
|
708
|
+
</IntlayerProvider>
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// NotFoundLayout wraps the 404 component with IntlayerProvider
|
|
713
|
+
// This ensures translations still work on the 404 page
|
|
714
|
+
function NotFoundLayout() {
|
|
715
|
+
const { defaultLocale } = useLocale();
|
|
716
|
+
const { locale } = Route.useParams();
|
|
717
|
+
|
|
718
|
+
return (
|
|
719
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
720
|
+
<NotFoundComponent />
|
|
721
|
+
{/* Include LocaleSwitcher so users can change language even on 404 */}
|
|
722
|
+
<LocaleSwitcher />
|
|
723
|
+
</IntlayerProvider>
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
729
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
730
|
+
|
|
731
|
+
import { NotFoundComponent } from "./404";
|
|
732
|
+
|
|
733
|
+
// The $ (splat/catch-all) route matches any path that doesn't match other routes
|
|
734
|
+
// e.g., /en/some/deeply/nested/invalid/path
|
|
735
|
+
// This ensures ALL unmatched paths within a locale show the 404 page
|
|
736
|
+
// Without this, unmatched deep paths might show a blank page or error
|
|
737
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
738
|
+
component: NotFoundComponent,
|
|
739
|
+
});
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
### Step 15: Configure TypeScript (Optional)
|
|
615
745
|
|
|
616
746
|
Intlayer uses module augmentation to get benefits of TypeScript and make your codebase stronger.
|
|
617
747
|
|
|
@@ -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)
|
|
@@ -602,7 +605,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
602
605
|
|
|
603
606
|
---
|
|
604
607
|
|
|
605
|
-
### Step 14:
|
|
608
|
+
### Step 14: Manage not found pages (Optional)
|
|
609
|
+
|
|
610
|
+
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.
|
|
611
|
+
|
|
612
|
+
#### Understanding TanStack Router's 404 Handling with Locale Prefixes
|
|
613
|
+
|
|
614
|
+
In TanStack Router, handling 404 pages with localized routes requires a multi-layered approach:
|
|
615
|
+
|
|
616
|
+
1. **Dedicated 404 route**: A specific route to display the 404 UI
|
|
617
|
+
2. **Route-level validation**: Validates locale prefixes and redirects invalid ones to 404
|
|
618
|
+
3. **Catch-all route**: Captures any unmatched paths within the locale segment
|
|
619
|
+
|
|
620
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
621
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
622
|
+
|
|
623
|
+
// This creates a dedicated /[locale]/404 route
|
|
624
|
+
// It's used both as a direct route and imported as a component in other files
|
|
625
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
626
|
+
component: NotFoundComponent,
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
// Exported separately so it can be reused in notFoundComponent and catch-all routes
|
|
630
|
+
export function NotFoundComponent() {
|
|
631
|
+
return (
|
|
632
|
+
<div>
|
|
633
|
+
<h1>404</h1>
|
|
634
|
+
</div>
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
640
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
641
|
+
|
|
642
|
+
// The root route serves as the top-level layout
|
|
643
|
+
// It doesn't handle 404s directly - that's delegated to child routes
|
|
644
|
+
// This keeps the root simple and lets locale-aware routes manage their own 404 logic
|
|
645
|
+
export const Route = createRootRoute({
|
|
646
|
+
component: Outlet,
|
|
647
|
+
});
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
651
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
652
|
+
import { validatePrefix } from "intlayer";
|
|
653
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
654
|
+
|
|
655
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
656
|
+
import { NotFoundComponent } from "./404";
|
|
657
|
+
|
|
658
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
659
|
+
// beforeLoad runs before the route renders (on both server and client)
|
|
660
|
+
// It's the ideal place to validate the locale prefix
|
|
661
|
+
beforeLoad: ({ params }) => {
|
|
662
|
+
// Get locale from route params (not from server headers, as beforeLoad runs on both client and server)
|
|
663
|
+
const localeParam = params.locale;
|
|
664
|
+
|
|
665
|
+
// validatePrefix checks if the locale is valid according to your intlayer config
|
|
666
|
+
// Returns: { isValid: boolean, localePrefix: string }
|
|
667
|
+
// - isValid: true if the prefix matches a configured locale (or is empty when prefix is optional)
|
|
668
|
+
// - localePrefix: the validated prefix or the default locale prefix for redirects
|
|
669
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
670
|
+
|
|
671
|
+
if (isValid) {
|
|
672
|
+
// Locale is valid, allow the route to render normally
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Invalid locale prefix (e.g., /xyz/about where "xyz" isn't a valid locale)
|
|
677
|
+
// Redirect to the 404 page with a valid locale prefix
|
|
678
|
+
// This ensures the 404 page is still properly localized
|
|
679
|
+
throw redirect({
|
|
680
|
+
to: "/{-$locale}/404",
|
|
681
|
+
params: { locale: localePrefix },
|
|
682
|
+
});
|
|
683
|
+
},
|
|
684
|
+
component: RouteComponent,
|
|
685
|
+
// notFoundComponent is called when a child route doesn't exist
|
|
686
|
+
// e.g., /en/non-existent-page triggers this within the /en layout
|
|
687
|
+
notFoundComponent: NotFoundLayout,
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
function RouteComponent() {
|
|
691
|
+
const { defaultLocale } = useLocale();
|
|
692
|
+
const { locale } = Route.useParams();
|
|
693
|
+
|
|
694
|
+
return (
|
|
695
|
+
// Wrap the entire locale segment with IntlayerProvider
|
|
696
|
+
// Falls back to defaultLocale when locale param is undefined (optional prefix mode)
|
|
697
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
698
|
+
<Outlet />
|
|
699
|
+
</IntlayerProvider>
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// NotFoundLayout wraps the 404 component with IntlayerProvider
|
|
704
|
+
// This ensures translations still work on the 404 page
|
|
705
|
+
function NotFoundLayout() {
|
|
706
|
+
const { defaultLocale } = useLocale();
|
|
707
|
+
const { locale } = Route.useParams();
|
|
708
|
+
|
|
709
|
+
return (
|
|
710
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
711
|
+
<NotFoundComponent />
|
|
712
|
+
{/* Include LocaleSwitcher so users can change language even on 404 */}
|
|
713
|
+
<LocaleSwitcher />
|
|
714
|
+
</IntlayerProvider>
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
720
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
721
|
+
|
|
722
|
+
import { NotFoundComponent } from "./404";
|
|
723
|
+
|
|
724
|
+
// The $ (splat/catch-all) route matches any path that doesn't match other routes
|
|
725
|
+
// e.g., /en/some/deeply/nested/invalid/path
|
|
726
|
+
// This ensures ALL unmatched paths within a locale show the 404 page
|
|
727
|
+
// Without this, unmatched deep paths might show a blank page or error
|
|
728
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
729
|
+
component: NotFoundComponent,
|
|
730
|
+
});
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
---
|
|
734
|
+
|
|
735
|
+
### Step 15: Configure TypeScript (Optional)
|
|
606
736
|
|
|
607
737
|
Intlayer uses module augmentation to benefit from TypeScript and strengthen your codebase.
|
|
608
738
|
|