@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: Introdotto validatePrefix e aggiunto il passaggio 14: Gestione delle pagine 404 con rotte localizzate.
|
|
22
25
|
- version: 7.3.9
|
|
23
26
|
date: 2025-12-05
|
|
24
|
-
changes:
|
|
27
|
+
changes: Aggiunto passaggio 13: Recupera la lingua locale nelle server actions (Opzionale)
|
|
25
28
|
- version: 6.5.2
|
|
26
29
|
date: 2025-10-03
|
|
27
30
|
changes: Aggiornamento documentazione
|
|
@@ -622,7 +625,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
622
625
|
|
|
623
626
|
---
|
|
624
627
|
|
|
625
|
-
### Passo 14:
|
|
628
|
+
### Passo 14: Gestire le pagine non trovate (Opzionale)
|
|
629
|
+
|
|
630
|
+
Quando un utente visita una pagina inesistente, puoi visualizzare una pagina personalizzata di non trovata e il prefisso locale può influenzare il modo in cui viene attivata la pagina di non trovata.
|
|
631
|
+
|
|
632
|
+
#### Comprendere la gestione 404 di TanStack Router con prefissi locale
|
|
633
|
+
|
|
634
|
+
In TanStack Router, gestire le pagine 404 con route localizzate richiede un approccio multistrato:
|
|
635
|
+
|
|
636
|
+
1. **Route 404 dedicata**: Una route specifica per visualizzare l'interfaccia utente 404
|
|
637
|
+
2. **Validazione a livello di route**: Valida i prefissi locale e reindirizza quelli non validi a 404
|
|
638
|
+
3. **Route catch-all**: Cattura tutti i percorsi non corrispondenti all'interno del segmento locale
|
|
639
|
+
|
|
640
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
641
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
642
|
+
|
|
643
|
+
// Questo crea una route dedicata /[locale]/404
|
|
644
|
+
// Viene utilizzata sia come route diretta che importata come componente in altri file
|
|
645
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
646
|
+
component: NotFoundComponent,
|
|
647
|
+
});
|
|
648
|
+
|
|
649
|
+
// Esportato separatamente in modo che possa essere riutilizzato in notFoundComponent e route catch-all
|
|
650
|
+
export function NotFoundComponent() {
|
|
651
|
+
return (
|
|
652
|
+
<div>
|
|
653
|
+
<h1>404</h1>
|
|
654
|
+
</div>
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
660
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
661
|
+
|
|
662
|
+
// La route radice funge da layout di livello superiore
|
|
663
|
+
// Non gestisce i 404 direttamente - questo è delegato alle route figlie
|
|
664
|
+
// Questo mantiene la radice semplice e consente alle route consapevoli della locale di gestire la propria logica 404
|
|
665
|
+
export const Route = createRootRoute({
|
|
666
|
+
component: Outlet,
|
|
667
|
+
});
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
671
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
672
|
+
import { validatePrefix } from "intlayer";
|
|
673
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
674
|
+
|
|
675
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
676
|
+
import { NotFoundComponent } from "./404";
|
|
677
|
+
|
|
678
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
679
|
+
// beforeLoad viene eseguito prima che la route venga renderizzata (sia sul server che sul client)
|
|
680
|
+
// È il posto ideale per validare il prefisso della locale
|
|
681
|
+
beforeLoad: ({ params }) => {
|
|
682
|
+
// Ottieni la locale dai parametri della route (non dagli header del server, poiché beforeLoad viene eseguito sia sul client che sul server)
|
|
683
|
+
const localeParam = params.locale;
|
|
684
|
+
|
|
685
|
+
// validatePrefix verifica se la locale è valida secondo la tua configurazione intlayer
|
|
686
|
+
// Restituisce: { isValid: boolean, localePrefix: string }
|
|
687
|
+
// - isValid: true se il prefisso corrisponde a una locale configurata (o è vuoto quando il prefisso è opzionale)
|
|
688
|
+
// - localePrefix: il prefisso validato o il prefisso della locale predefinito per i reindirizzamenti
|
|
689
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
690
|
+
|
|
691
|
+
if (isValid) {
|
|
692
|
+
// La locale è valida, consenti alla route di renderizzarsi normalmente
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Prefisso della locale non valido (ad esempio, /xyz/about dove "xyz" non è una locale valida)
|
|
697
|
+
// Reindirizza alla pagina 404 con un prefisso della locale valido
|
|
698
|
+
// Questo assicura che la pagina 404 sia ancora correttamente localizzata
|
|
699
|
+
throw redirect({
|
|
700
|
+
to: "/{-$locale}/404",
|
|
701
|
+
params: { locale: localePrefix },
|
|
702
|
+
});
|
|
703
|
+
},
|
|
704
|
+
component: RouteComponent,
|
|
705
|
+
// notFoundComponent viene chiamato quando una route figlia non esiste
|
|
706
|
+
// ad esempio, /en/pagina-inesistente attiva questo all'interno del layout /en
|
|
707
|
+
notFoundComponent: NotFoundLayout,
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
function RouteComponent() {
|
|
711
|
+
const { defaultLocale } = useLocale();
|
|
712
|
+
const { locale } = Route.useParams();
|
|
713
|
+
|
|
714
|
+
return (
|
|
715
|
+
// Avvolgi l'intero segmento della locale con IntlayerProvider
|
|
716
|
+
// Torna a defaultLocale quando il parametro locale è undefined (modalità prefisso opzionale)
|
|
717
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
718
|
+
<Outlet />
|
|
719
|
+
</IntlayerProvider>
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// NotFoundLayout avvolge il componente 404 con IntlayerProvider
|
|
724
|
+
// Questo assicura che le traduzioni funzionino ancora sulla pagina 404
|
|
725
|
+
function NotFoundLayout() {
|
|
726
|
+
const { defaultLocale } = useLocale();
|
|
727
|
+
const { locale } = Route.useParams();
|
|
728
|
+
|
|
729
|
+
return (
|
|
730
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
731
|
+
<NotFoundComponent />
|
|
732
|
+
{/* Includi LocaleSwitcher in modo che gli utenti possano cambiare lingua anche su 404 */}
|
|
733
|
+
<LocaleSwitcher />
|
|
734
|
+
</IntlayerProvider>
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
740
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
741
|
+
|
|
742
|
+
import { NotFoundComponent } from "./404";
|
|
743
|
+
|
|
744
|
+
// La route $ (splat/catch-all) corrisponde a qualsiasi percorso che non corrisponde ad altre route
|
|
745
|
+
// ad esempio, /en/qualche/percorso/profondamente/annidato/non-valido
|
|
746
|
+
// Questo assicura che TUTTI i percorsi non corrispondenti all'interno di una locale mostrino la pagina 404
|
|
747
|
+
// Senza questo, i percorsi profondi non corrispondenti potrebbero mostrare una pagina vuota o un errore
|
|
748
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
749
|
+
component: NotFoundComponent,
|
|
750
|
+
});
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
---
|
|
754
|
+
|
|
755
|
+
### Passo 15: Configurare TypeScript (Opzionale)
|
|
626
756
|
|
|
627
757
|
Intlayer utilizza l'augmentation dei moduli per sfruttare i vantaggi di TypeScript e rendere il tuo codice più robusto.
|
|
628
758
|
|
|
@@ -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 用に追加
|
|
@@ -594,7 +597,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
594
597
|
|
|
595
598
|
---
|
|
596
599
|
|
|
597
|
-
### ステップ14:
|
|
600
|
+
### ステップ14: 見つからないページの管理(任意)
|
|
601
|
+
|
|
602
|
+
ユーザーが存在しないページにアクセスした場合、カスタムの見つからないページを表示でき、ロケールプレフィックスが見つからないページのトリガー方法に影響を与える可能性があります。
|
|
603
|
+
|
|
604
|
+
#### ロケールプレフィックスを使用したTanStack Routerの404処理を理解する
|
|
605
|
+
|
|
606
|
+
TanStack Routerでは、ローカライズされたルートで404ページを処理するには、多層的なアプローチが必要です:
|
|
607
|
+
|
|
608
|
+
1. **専用の404ルート**: 404 UIを表示するための特定のルート
|
|
609
|
+
2. **ルートレベルの検証**: ロケールプレフィックスを検証し、無効なものを404にリダイレクト
|
|
610
|
+
3. **キャッチオールルート**: ロケールセグメント内で一致しないすべてのパスをキャプチャ
|
|
611
|
+
|
|
612
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
613
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
614
|
+
|
|
615
|
+
// これは専用の /[locale]/404 ルートを作成します
|
|
616
|
+
// 直接ルートとして使用されるか、他のファイルでコンポーネントとしてインポートされます
|
|
617
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
618
|
+
component: NotFoundComponent,
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
// notFoundComponent および catch-all ルートで再利用できるように個別にエクスポートされます
|
|
622
|
+
export function NotFoundComponent() {
|
|
623
|
+
return (
|
|
624
|
+
<div>
|
|
625
|
+
<h1>404</h1>
|
|
626
|
+
</div>
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
632
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
633
|
+
|
|
634
|
+
// ルートルートは最上位レイアウトとして機能します
|
|
635
|
+
// 404を直接処理しません - それは子ルートに委任されます
|
|
636
|
+
// これにより、ルートをシンプルに保ち、ロケール対応ルートが独自の404ロジックを管理できるようになります
|
|
637
|
+
export const Route = createRootRoute({
|
|
638
|
+
component: Outlet,
|
|
639
|
+
});
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
643
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
644
|
+
import { validatePrefix } from "intlayer";
|
|
645
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
646
|
+
|
|
647
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
648
|
+
import { NotFoundComponent } from "./404";
|
|
649
|
+
|
|
650
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
651
|
+
// beforeLoadはルートがレンダリングされる前に実行されます(サーバーとクライアントの両方で)
|
|
652
|
+
// ロケールプレフィックスを検証するのに理想的な場所です
|
|
653
|
+
beforeLoad: ({ params }) => {
|
|
654
|
+
// ルートパラメータからロケールを取得(サーバーヘッダーからではない。beforeLoadはクライアントとサーバーの両方で実行されるため)
|
|
655
|
+
const localeParam = params.locale;
|
|
656
|
+
|
|
657
|
+
// validatePrefixは、ロケールがintlayer設定に従って有効かどうかをチェックします
|
|
658
|
+
// 戻り値: { isValid: boolean, localePrefix: string }
|
|
659
|
+
// - isValid: プレフィックスが設定されたロケールと一致する場合(またはプレフィックスがオプションの場合は空)はtrue
|
|
660
|
+
// - localePrefix: 検証されたプレフィックスまたはリダイレクト用のデフォルトのロケールプレフィックス
|
|
661
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
662
|
+
|
|
663
|
+
if (isValid) {
|
|
664
|
+
// ロケールが有効です。ルートが正常にレンダリングされるようにします
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// 無効なロケールプレフィックス(例: "xyz"が有効なロケールではない /xyz/about)
|
|
669
|
+
// 有効なロケールプレフィックスで404ページにリダイレクト
|
|
670
|
+
// これにより、404ページが適切にローカライズされたままになります
|
|
671
|
+
throw redirect({
|
|
672
|
+
to: "/{-$locale}/404",
|
|
673
|
+
params: { locale: localePrefix },
|
|
674
|
+
});
|
|
675
|
+
},
|
|
676
|
+
component: RouteComponent,
|
|
677
|
+
// notFoundComponentは子ルートが存在しないときに呼び出されます
|
|
678
|
+
// 例: /en/存在しないページが /en レイアウト内でこれをトリガーします
|
|
679
|
+
notFoundComponent: NotFoundLayout,
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
function RouteComponent() {
|
|
683
|
+
const { defaultLocale } = useLocale();
|
|
684
|
+
const { locale } = Route.useParams();
|
|
685
|
+
|
|
686
|
+
return (
|
|
687
|
+
// ロケールセグメント全体をIntlayerProviderでラップ
|
|
688
|
+
// ロケールパラメータがundefinedの場合、defaultLocaleにフォールバック(オプションプレフィックスモード)
|
|
689
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
690
|
+
<Outlet />
|
|
691
|
+
</IntlayerProvider>
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
// NotFoundLayoutは404コンポーネントをIntlayerProviderでラップします
|
|
696
|
+
// これにより、404ページで翻訳が引き続き機能することが保証されます
|
|
697
|
+
function NotFoundLayout() {
|
|
698
|
+
const { defaultLocale } = useLocale();
|
|
699
|
+
const { locale } = Route.useParams();
|
|
700
|
+
|
|
701
|
+
return (
|
|
702
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
703
|
+
<NotFoundComponent />
|
|
704
|
+
{/* ユーザーが404でも言語を変更できるようにLocaleSwitcherを含める */}
|
|
705
|
+
<LocaleSwitcher />
|
|
706
|
+
</IntlayerProvider>
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
712
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
713
|
+
|
|
714
|
+
import { NotFoundComponent } from "./404";
|
|
715
|
+
|
|
716
|
+
// $ (splat/catch-all) ルートは、他のルートと一致しない任意のパスに一致します
|
|
717
|
+
// 例: /en/いくつかの/深く/ネストされた/無効な/パス
|
|
718
|
+
// これにより、ロケール内の一致しないすべてのパスが404ページを表示することが保証されます
|
|
719
|
+
// これがないと、一致しない深いパスが空白ページやエラーを表示する可能性があります
|
|
720
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
721
|
+
component: NotFoundComponent,
|
|
722
|
+
});
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
### ステップ15: TypeScriptの設定(任意)
|
|
598
728
|
|
|
599
729
|
Intlayerはモジュール拡張を使用して、TypeScriptの利点を活かし、コードベースを強化します。
|
|
600
730
|
|
|
@@ -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단계 추가: 서버 액션에서 locale 가져오기 (선택 사항)
|
|
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
|
+
#### 로케일 접두사로 TanStack Router의 404 처리 이해하기
|
|
610
|
+
|
|
611
|
+
TanStack Router에서 현지화된 경로로 404 페이지를 처리하려면 다층 접근 방식이 필요합니다:
|
|
612
|
+
|
|
613
|
+
1. **전용 404 경로**: 404 UI를 표시하는 특정 경로
|
|
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"가 유효한 로케일이 아닌 /xyz/about)
|
|
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
|
+
// 로케일 매개변수가 undefined일 때 defaultLocale로 폴백 (선택적 접두사 모드)
|
|
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
|
+
{/* 사용자가 404에서도 언어를 변경할 수 있도록 LocaleSwitcher 포함 */}
|
|
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는 모듈 확장을 사용하여 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: Wprowadzenie validatePrefix oraz dodanie kroku 14: Obsługa stron 404 z lokalizowanymi trasami.
|
|
22
25
|
- version: 7.3.9
|
|
23
26
|
date: 2025-12-05
|
|
24
|
-
changes:
|
|
27
|
+
changes: Dodany krok 13: Pobieranie lokalizacji w akcjach serwerowych (Opcjonalnie)
|
|
25
28
|
- version: 6.5.2
|
|
26
29
|
date: 2025-10-03
|
|
27
30
|
changes: Aktualizacja dokumentacji
|
|
@@ -590,7 +593,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
590
593
|
|
|
591
594
|
---
|
|
592
595
|
|
|
593
|
-
### Krok 14:
|
|
596
|
+
### Krok 14: Zarządzanie stronami nie znalezionymi (opcjonalnie)
|
|
597
|
+
|
|
598
|
+
Gdy użytkownik odwiedza nieistniejącą stronę, możesz wyświetlić niestandardową stronę "nie znaleziono", a prefiks locale może wpływać na sposób wyzwalania strony "nie znaleziono".
|
|
599
|
+
|
|
600
|
+
#### Zrozumienie obsługi 404 w TanStack Router z prefiksami locale
|
|
601
|
+
|
|
602
|
+
W TanStack Router obsługa stron 404 z zlokalizowanymi trasami wymaga podejścia wielowarstwowego:
|
|
603
|
+
|
|
604
|
+
1. **Dedykowana trasa 404**: Konkretna trasa do wyświetlenia interfejsu 404
|
|
605
|
+
2. **Walidacja na poziomie trasy**: Weryfikuje prefiksy locale i przekierowuje nieprawidłowe do 404
|
|
606
|
+
3. **Trasa catch-all**: Przechwytuje wszystkie niedopasowane ścieżki w segmencie locale
|
|
607
|
+
|
|
608
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
609
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
610
|
+
|
|
611
|
+
// To tworzy dedykowaną trasę /[locale]/404
|
|
612
|
+
// Jest używana zarówno jako bezpośrednia trasa, jak i importowana jako komponent w innych plikach
|
|
613
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
614
|
+
component: NotFoundComponent,
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
// Eksportowane osobno, aby można było ponownie użyć w notFoundComponent i trasach catch-all
|
|
618
|
+
export function NotFoundComponent() {
|
|
619
|
+
return (
|
|
620
|
+
<div>
|
|
621
|
+
<h1>404</h1>
|
|
622
|
+
</div>
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
628
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
629
|
+
|
|
630
|
+
// Trasa główna służy jako układ najwyższego poziomu
|
|
631
|
+
// Nie obsługuje 404 bezpośrednio - to jest delegowane do tras potomnych
|
|
632
|
+
// To utrzymuje główną trasę prostą i pozwala trasom świadomym locale zarządzać własną logiką 404
|
|
633
|
+
export const Route = createRootRoute({
|
|
634
|
+
component: Outlet,
|
|
635
|
+
});
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
639
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
640
|
+
import { validatePrefix } from "intlayer";
|
|
641
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
642
|
+
|
|
643
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
644
|
+
import { NotFoundComponent } from "./404";
|
|
645
|
+
|
|
646
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
647
|
+
// beforeLoad uruchamia się przed renderowaniem trasy (zarówno na serwerze, jak i kliencie)
|
|
648
|
+
// To idealne miejsce do walidacji prefiksu locale
|
|
649
|
+
beforeLoad: ({ params }) => {
|
|
650
|
+
// Pobierz locale z parametrów trasy (nie z nagłówków serwera, ponieważ beforeLoad działa zarówno na kliencie, jak i serwerze)
|
|
651
|
+
const localeParam = params.locale;
|
|
652
|
+
|
|
653
|
+
// validatePrefix sprawdza, czy locale jest prawidłowe zgodnie z konfiguracją intlayer
|
|
654
|
+
// Zwraca: { isValid: boolean, localePrefix: string }
|
|
655
|
+
// - isValid: true, jeśli prefiks pasuje do skonfigurowanego locale (lub jest pusty, gdy prefiks jest opcjonalny)
|
|
656
|
+
// - localePrefix: zwalidowany prefiks lub domyślny prefiks locale do przekierowań
|
|
657
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
658
|
+
|
|
659
|
+
if (isValid) {
|
|
660
|
+
// Locale jest prawidłowe, pozwól trasie renderować się normalnie
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Nieprawidłowy prefiks locale (np. /xyz/about, gdzie "xyz" nie jest prawidłowym locale)
|
|
665
|
+
// Przekieruj do strony 404 z prawidłowym prefiksem locale
|
|
666
|
+
// To zapewnia, że strona 404 jest nadal prawidłowo zlokalizowana
|
|
667
|
+
throw redirect({
|
|
668
|
+
to: "/{-$locale}/404",
|
|
669
|
+
params: { locale: localePrefix },
|
|
670
|
+
});
|
|
671
|
+
},
|
|
672
|
+
component: RouteComponent,
|
|
673
|
+
// notFoundComponent jest wywoływane, gdy trasa potomna nie istnieje
|
|
674
|
+
// np. /en/nieistniejaca-strona wyzwala to w układzie /en
|
|
675
|
+
notFoundComponent: NotFoundLayout,
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
function RouteComponent() {
|
|
679
|
+
const { defaultLocale } = useLocale();
|
|
680
|
+
const { locale } = Route.useParams();
|
|
681
|
+
|
|
682
|
+
return (
|
|
683
|
+
// Owiń cały segment locale w IntlayerProvider
|
|
684
|
+
// Powraca do defaultLocale, gdy parametr locale jest undefined (tryb opcjonalnego prefiksu)
|
|
685
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
686
|
+
<Outlet />
|
|
687
|
+
</IntlayerProvider>
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// NotFoundLayout owija komponent 404 w IntlayerProvider
|
|
692
|
+
// To zapewnia, że tłumaczenia nadal działają na stronie 404
|
|
693
|
+
function NotFoundLayout() {
|
|
694
|
+
const { defaultLocale } = useLocale();
|
|
695
|
+
const { locale } = Route.useParams();
|
|
696
|
+
|
|
697
|
+
return (
|
|
698
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
699
|
+
<NotFoundComponent />
|
|
700
|
+
{/* Dołącz LocaleSwitcher, aby użytkownicy mogli zmieniać język nawet na 404 */}
|
|
701
|
+
<LocaleSwitcher />
|
|
702
|
+
</IntlayerProvider>
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
708
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
709
|
+
|
|
710
|
+
import { NotFoundComponent } from "./404";
|
|
711
|
+
|
|
712
|
+
// Trasa $ (splat/catch-all) pasuje do każdej ścieżki, która nie pasuje do innych tras
|
|
713
|
+
// np. /en/jakas/gleboko/zagniezdzona/niewazna/sciezka
|
|
714
|
+
// To zapewnia, że WSZYSTKIE niedopasowane ścieżki w locale wyświetlają stronę 404
|
|
715
|
+
// Bez tego niedopasowane głębokie ścieżki mogą wyświetlać pustą stronę lub błąd
|
|
716
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
717
|
+
component: NotFoundComponent,
|
|
718
|
+
});
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
### Krok 15: Konfiguracja TypeScript (opcjonalnie)
|
|
594
724
|
|
|
595
725
|
Intlayer używa rozszerzenia modułów (module augmentation), aby wykorzystać zalety TypeScript i wzmocnić Twoją bazę kodu.
|
|
596
726
|
|