@intlayer/docs 7.3.14 → 7.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/blog/ar/intlayer_with_i18next.md +3 -0
- package/blog/ar/intlayer_with_next-i18next.md +3 -0
- package/blog/ar/intlayer_with_next-intl.md +3 -0
- package/blog/ar/intlayer_with_react-i18next.md +3 -0
- package/blog/ar/intlayer_with_react-intl.md +3 -0
- package/blog/ar/intlayer_with_vue-i18n.md +3 -0
- package/blog/de/intlayer_with_i18next.md +3 -0
- package/blog/de/intlayer_with_next-i18next.md +3 -0
- package/blog/de/intlayer_with_next-intl.md +3 -0
- package/blog/de/intlayer_with_react-i18next.md +3 -0
- package/blog/de/intlayer_with_react-intl.md +3 -0
- package/blog/de/intlayer_with_vue-i18n.md +3 -0
- package/blog/en/intlayer_with_i18next.md +7 -0
- package/blog/en/intlayer_with_next-i18next.md +3 -0
- package/blog/en/intlayer_with_next-intl.md +7 -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 +3 -0
- package/blog/en-GB/intlayer_with_next-i18next.md +3 -0
- package/blog/en-GB/intlayer_with_next-intl.md +3 -0
- package/blog/en-GB/intlayer_with_react-i18next.md +3 -0
- package/blog/en-GB/intlayer_with_react-intl.md +3 -0
- package/blog/en-GB/intlayer_with_vue-i18n.md +3 -0
- package/blog/es/intlayer_with_i18next.md +3 -0
- package/blog/es/intlayer_with_next-i18next.md +3 -0
- package/blog/es/intlayer_with_next-intl.md +3 -0
- package/blog/es/intlayer_with_react-i18next.md +3 -0
- package/blog/es/intlayer_with_react-intl.md +3 -0
- package/blog/es/intlayer_with_vue-i18n.md +3 -0
- package/blog/fr/intlayer_with_i18next.md +3 -0
- package/blog/fr/intlayer_with_next-i18next.md +3 -0
- package/blog/fr/intlayer_with_next-intl.md +3 -0
- package/blog/fr/intlayer_with_react-i18next.md +3 -0
- package/blog/fr/intlayer_with_react-intl.md +3 -0
- package/blog/fr/intlayer_with_vue-i18n.md +3 -0
- package/blog/hi/intlayer_with_i18next.md +3 -0
- package/blog/hi/intlayer_with_next-i18next.md +3 -0
- package/blog/hi/intlayer_with_next-intl.md +3 -0
- package/blog/hi/intlayer_with_react-i18next.md +3 -0
- package/blog/hi/intlayer_with_react-intl.md +3 -0
- package/blog/hi/intlayer_with_vue-i18n.md +3 -0
- package/blog/id/intlayer_with_i18next.md +3 -0
- package/blog/id/intlayer_with_next-i18next.md +3 -0
- package/blog/id/intlayer_with_next-intl.md +3 -0
- package/blog/id/intlayer_with_react-i18next.md +3 -0
- package/blog/id/intlayer_with_react-intl.md +3 -0
- package/blog/id/intlayer_with_vue-i18n.md +3 -0
- package/blog/it/intlayer_with_i18next.md +3 -0
- package/blog/it/intlayer_with_next-i18next.md +3 -0
- package/blog/it/intlayer_with_next-intl.md +3 -0
- package/blog/it/intlayer_with_react-i18next.md +3 -0
- package/blog/it/intlayer_with_react-intl.md +3 -0
- package/blog/it/intlayer_with_vue-i18n.md +3 -0
- package/blog/ja/intlayer_with_i18next.md +3 -0
- package/blog/ja/intlayer_with_next-i18next.md +3 -0
- package/blog/ja/intlayer_with_next-intl.md +3 -0
- package/blog/ja/intlayer_with_react-i18next.md +3 -0
- package/blog/ja/intlayer_with_react-intl.md +3 -0
- package/blog/ja/intlayer_with_vue-i18n.md +3 -0
- package/blog/ko/intlayer_with_i18next.md +3 -0
- package/blog/ko/intlayer_with_next-i18next.md +3 -0
- package/blog/ko/intlayer_with_next-intl.md +3 -0
- package/blog/ko/intlayer_with_react-i18next.md +3 -0
- package/blog/ko/intlayer_with_react-intl.md +3 -0
- package/blog/ko/intlayer_with_vue-i18n.md +3 -0
- package/blog/pl/intlayer_with_i18next.md +3 -0
- package/blog/pl/intlayer_with_next-i18next.md +3 -0
- package/blog/pl/intlayer_with_next-intl.md +3 -0
- package/blog/pl/intlayer_with_react-i18next.md +3 -0
- package/blog/pl/intlayer_with_react-intl.md +3 -0
- package/blog/pl/intlayer_with_vue-i18n.md +3 -0
- package/blog/pt/intlayer_with_i18next.md +3 -0
- package/blog/pt/intlayer_with_next-i18next.md +3 -0
- package/blog/pt/intlayer_with_next-intl.md +3 -0
- package/blog/pt/intlayer_with_react-i18next.md +3 -0
- package/blog/pt/intlayer_with_react-intl.md +3 -0
- package/blog/pt/intlayer_with_vue-i18n.md +3 -0
- package/blog/ru/intlayer_with_i18next.md +3 -0
- package/blog/ru/intlayer_with_next-i18next.md +3 -0
- package/blog/ru/intlayer_with_next-intl.md +3 -0
- package/blog/ru/intlayer_with_react-i18next.md +3 -0
- package/blog/ru/intlayer_with_react-intl.md +3 -0
- package/blog/ru/intlayer_with_vue-i18n.md +3 -0
- package/blog/tr/intlayer_with_i18next.md +3 -0
- package/blog/tr/intlayer_with_next-i18next.md +3 -0
- package/blog/tr/intlayer_with_next-intl.md +3 -0
- package/blog/tr/intlayer_with_react-i18next.md +3 -0
- package/blog/tr/intlayer_with_vue-i18n.md +3 -0
- package/blog/vi/intlayer_with_i18next.md +3 -0
- package/blog/vi/intlayer_with_next-i18next.md +3 -0
- package/blog/vi/intlayer_with_next-intl.md +3 -0
- package/blog/vi/intlayer_with_react-i18next.md +3 -0
- package/blog/vi/intlayer_with_react-intl.md +3 -0
- package/blog/vi/intlayer_with_vue-i18n.md +3 -0
- package/blog/zh/intlayer_with_i18next.md +3 -0
- package/blog/zh/intlayer_with_next-i18next.md +3 -0
- package/blog/zh/intlayer_with_next-intl.md +3 -0
- package/blog/zh/intlayer_with_react-i18next.md +3 -0
- package/blog/zh/intlayer_with_react-intl.md +3 -0
- package/blog/zh/intlayer_with_vue-i18n.md +3 -0
- package/docs/ar/intlayer_with_lynx+react.md +1 -1
- package/docs/ar/intlayer_with_tanstack.md +132 -2
- package/docs/ar/intlayer_with_vite+react.md +99 -331
- package/docs/ar/plugins/sync-json.md +3 -0
- package/docs/de/intlayer_with_lynx+react.md +1 -1
- package/docs/de/intlayer_with_tanstack.md +132 -2
- package/docs/de/intlayer_with_vite+react.md +116 -380
- package/docs/de/plugins/sync-json.md +3 -0
- package/docs/en/intlayer_with_tanstack.md +131 -1
- package/docs/en/intlayer_with_vite+react.md +6 -10
- package/docs/en/plugins/sync-json.md +3 -0
- package/docs/en-GB/intlayer_with_tanstack.md +131 -1
- package/docs/en-GB/intlayer_with_vite+react.md +62 -74
- package/docs/en-GB/plugins/sync-json.md +3 -0
- package/docs/es/intlayer_with_tanstack.md +132 -2
- package/docs/es/intlayer_with_vite+react.md +101 -333
- package/docs/es/plugins/sync-json.md +3 -0
- package/docs/fr/intlayer_with_tanstack.md +132 -2
- package/docs/fr/intlayer_with_vite+react.md +101 -357
- package/docs/fr/plugins/sync-json.md +3 -0
- package/docs/hi/intlayer_with_tanstack.md +132 -2
- package/docs/hi/intlayer_with_vite+react.md +120 -333
- package/docs/hi/plugins/sync-json.md +3 -0
- package/docs/id/intlayer_with_tanstack.md +132 -2
- package/docs/id/intlayer_with_vite+react.md +7 -13
- package/docs/id/plugins/sync-json.md +3 -0
- package/docs/it/intlayer_with_lynx+react.md +1 -1
- package/docs/it/intlayer_with_tanstack.md +132 -2
- package/docs/it/intlayer_with_vite+react.md +121 -393
- package/docs/it/plugins/sync-json.md +3 -0
- package/docs/ja/intlayer_with_tanstack.md +132 -2
- package/docs/ja/intlayer_with_vite+react.md +106 -378
- package/docs/ja/plugins/sync-json.md +3 -0
- package/docs/ko/intlayer_with_lynx+react.md +1 -1
- package/docs/ko/intlayer_with_tanstack.md +132 -2
- package/docs/ko/intlayer_with_vite+react.md +90 -322
- package/docs/ko/plugins/sync-json.md +3 -0
- package/docs/pl/intlayer_with_tanstack.md +132 -2
- package/docs/pl/intlayer_with_vite+react.md +25 -21
- package/docs/pl/plugins/sync-json.md +3 -0
- package/docs/pt/intlayer_with_tanstack.md +132 -2
- package/docs/pt/intlayer_with_vite+react.md +96 -328
- package/docs/pt/plugins/sync-json.md +3 -0
- package/docs/ru/intlayer_with_lynx+react.md +1 -1
- package/docs/ru/intlayer_with_tanstack.md +132 -2
- package/docs/ru/intlayer_with_vite+react.md +109 -362
- package/docs/ru/plugins/sync-json.md +3 -0
- package/docs/tr/intlayer_with_tanstack.md +132 -2
- package/docs/tr/intlayer_with_vite+react.md +132 -366
- package/docs/tr/plugins/sync-json.md +3 -0
- package/docs/vi/intlayer_with_tanstack.md +132 -2
- package/docs/vi/intlayer_with_vite+react.md +16 -19
- package/docs/vi/plugins/sync-json.md +3 -0
- package/docs/zh/intlayer_with_tanstack.md +133 -3
- package/docs/zh/intlayer_with_vite+react.md +91 -374
- package/docs/zh/plugins/sync-json.md +3 -0
- package/frequent_questions/ar/customized_locale_list.md +1 -1
- package/frequent_questions/de/customized_locale_list.md +1 -1
- package/frequent_questions/en/customized_locale_list.md +1 -1
- package/frequent_questions/en-GB/customized_locale_list.md +1 -1
- package/frequent_questions/es/customized_locale_list.md +1 -1
- package/frequent_questions/fr/customized_locale_list.md +1 -1
- package/frequent_questions/hi/customized_locale_list.md +1 -1
- package/frequent_questions/id/customized_locale_list.md +1 -1
- package/frequent_questions/it/customized_locale_list.md +1 -1
- package/frequent_questions/ja/customized_locale_list.md +1 -1
- package/frequent_questions/ko/customized_locale_list.md +1 -1
- package/frequent_questions/pl/customized_locale_list.md +1 -1
- package/frequent_questions/pt/customized_locale_list.md +1 -1
- package/frequent_questions/ru/customized_locale_list.md +1 -1
- package/frequent_questions/tr/customized_locale_list.md +1 -1
- package/frequent_questions/vi/customized_locale_list.md +1 -1
- package/frequent_questions/zh/customized_locale_list.md +1 -1
- package/package.json +6 -6
|
@@ -22,6 +22,7 @@ slugs:
|
|
|
22
22
|
- doc
|
|
23
23
|
- plugin
|
|
24
24
|
- sync-json
|
|
25
|
+
youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
|
|
25
26
|
history:
|
|
26
27
|
- version: 6.1.6
|
|
27
28
|
date: 2025-10-05
|
|
@@ -30,6 +31,8 @@ history:
|
|
|
30
31
|
|
|
31
32
|
## सिंक JSON (i18n ब्रिजेस)
|
|
32
33
|
|
|
34
|
+
<iframe title="Intlayer के साथ अपने JSON अनुवादों को सिंक में कैसे रखें" 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
|
+
|
|
33
36
|
अपने मौजूदा i18n स्टैक में एक ऐड-ऑन के रूप में Intlayer का उपयोग करें। यह प्लगइन आपके JSON संदेशों को Intlayer शब्दकोशों के साथ सिंक्रनाइज़ रखता है ताकि आप:
|
|
34
37
|
|
|
35
38
|
- i18next, next-intl, react-intl, vue-i18n, next-translate, nuxt-i18n, Solid-i18next, svelte-i18n आदि को बनाए रख सकें।
|
|
@@ -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: Memperkenalkan validatePrefix dan menambah langkah 14: Menangani halaman 404 dengan rute terlokalisasi.
|
|
22
25
|
- version: 7.3.9
|
|
23
26
|
date: 2025-12-05
|
|
24
|
-
changes:
|
|
27
|
+
changes: Menambah langkah 13: Mengambil locale di server actions Anda (Opsional)
|
|
25
28
|
- version: 6.5.2
|
|
26
29
|
date: 2025-10-03
|
|
27
30
|
changes: Memperbarui dokumen
|
|
@@ -592,7 +595,134 @@ export const getLocaleServer = createServerFn().handler(async () => {
|
|
|
592
595
|
|
|
593
596
|
---
|
|
594
597
|
|
|
595
|
-
### Langkah 14:
|
|
598
|
+
### Langkah 14: Mengelola halaman tidak ditemukan (Opsional)
|
|
599
|
+
|
|
600
|
+
Ketika pengguna mengunjungi halaman yang tidak ada, Anda dapat menampilkan halaman tidak ditemukan yang disesuaikan dan awalan locale dapat mempengaruhi cara halaman tidak ditemukan dipicu.
|
|
601
|
+
|
|
602
|
+
#### Memahami Penanganan 404 TanStack Router dengan Awalan Locale
|
|
603
|
+
|
|
604
|
+
Di TanStack Router, menangani halaman 404 dengan rute yang dilokalisasi memerlukan pendekatan berlapis:
|
|
605
|
+
|
|
606
|
+
1. **Rute 404 khusus**: Rute spesifik untuk menampilkan UI 404
|
|
607
|
+
2. **Validasi tingkat rute**: Memvalidasi awalan locale dan mengarahkan ulang yang tidak valid ke 404
|
|
608
|
+
3. **Rute catch-all**: Menangkap semua jalur yang tidak cocok dalam segmen locale
|
|
609
|
+
|
|
610
|
+
```tsx fileName="src/routes/{-$locale}/404.tsx"
|
|
611
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
612
|
+
|
|
613
|
+
// Ini membuat rute khusus /[locale]/404
|
|
614
|
+
// Digunakan baik sebagai rute langsung maupun diimpor sebagai komponen di file lain
|
|
615
|
+
export const Route = createFileRoute("/{-$locale}/404")({
|
|
616
|
+
component: NotFoundComponent,
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
// Diekspor secara terpisah agar dapat digunakan kembali di notFoundComponent dan rute catch-all
|
|
620
|
+
export function NotFoundComponent() {
|
|
621
|
+
return (
|
|
622
|
+
<div>
|
|
623
|
+
<h1>404</h1>
|
|
624
|
+
</div>
|
|
625
|
+
);
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
630
|
+
import { createRootRoute } from "@tanstack/react-router";
|
|
631
|
+
|
|
632
|
+
// Rute root berfungsi sebagai tata letak tingkat atas
|
|
633
|
+
// Tidak menangani 404 secara langsung - itu didelegasikan ke rute anak
|
|
634
|
+
// Ini menjaga root tetap sederhana dan memungkinkan rute yang sadar locale mengelola logika 404 mereka sendiri
|
|
635
|
+
export const Route = createRootRoute({
|
|
636
|
+
component: Outlet,
|
|
637
|
+
});
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
```tsx fileName="src/routes/{-$locale}/route.tsx"
|
|
641
|
+
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";
|
|
642
|
+
import { validatePrefix } from "intlayer";
|
|
643
|
+
import { IntlayerProvider, useLocale } from "react-intlayer";
|
|
644
|
+
|
|
645
|
+
import { LocaleSwitcher } from "@/components/locale-switcher";
|
|
646
|
+
import { NotFoundComponent } from "./404";
|
|
647
|
+
|
|
648
|
+
export const Route = createFileRoute("/{-$locale}")({
|
|
649
|
+
// beforeLoad berjalan sebelum rute dirender (baik di server maupun klien)
|
|
650
|
+
// Ini adalah tempat ideal untuk memvalidasi awalan locale
|
|
651
|
+
beforeLoad: ({ params }) => {
|
|
652
|
+
// Dapatkan locale dari parameter rute (bukan dari header server, karena beforeLoad berjalan di klien dan server)
|
|
653
|
+
const localeParam = params.locale;
|
|
654
|
+
|
|
655
|
+
// validatePrefix memeriksa apakah locale valid menurut konfigurasi intlayer Anda
|
|
656
|
+
// Mengembalikan: { isValid: boolean, localePrefix: string }
|
|
657
|
+
// - isValid: true jika awalan cocok dengan locale yang dikonfigurasi (atau kosong ketika awalan opsional)
|
|
658
|
+
// - localePrefix: awalan yang divalidasi atau awalan locale default untuk pengalihan
|
|
659
|
+
const { isValid, localePrefix } = validatePrefix(localeParam);
|
|
660
|
+
|
|
661
|
+
if (isValid) {
|
|
662
|
+
// Locale valid, izinkan rute untuk dirender secara normal
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Awalan locale tidak valid (misalnya, /xyz/about di mana "xyz" bukan locale yang valid)
|
|
667
|
+
// Alihkan ke halaman 404 dengan awalan locale yang valid
|
|
668
|
+
// Ini memastikan halaman 404 masih dilokalkan dengan benar
|
|
669
|
+
throw redirect({
|
|
670
|
+
to: "/{-$locale}/404",
|
|
671
|
+
params: { locale: localePrefix },
|
|
672
|
+
});
|
|
673
|
+
},
|
|
674
|
+
component: RouteComponent,
|
|
675
|
+
// notFoundComponent dipanggil ketika rute anak tidak ada
|
|
676
|
+
// misalnya, /en/halaman-tidak-ada memicu ini dalam tata letak /en
|
|
677
|
+
notFoundComponent: NotFoundLayout,
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
function RouteComponent() {
|
|
681
|
+
const { defaultLocale } = useLocale();
|
|
682
|
+
const { locale } = Route.useParams();
|
|
683
|
+
|
|
684
|
+
return (
|
|
685
|
+
// Bungkus seluruh segmen locale dengan IntlayerProvider
|
|
686
|
+
// Kembali ke defaultLocale ketika parameter locale adalah undefined (mode awalan opsional)
|
|
687
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
688
|
+
<Outlet />
|
|
689
|
+
</IntlayerProvider>
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// NotFoundLayout membungkus komponen 404 dengan IntlayerProvider
|
|
694
|
+
// Ini memastikan terjemahan masih berfungsi di halaman 404
|
|
695
|
+
function NotFoundLayout() {
|
|
696
|
+
const { defaultLocale } = useLocale();
|
|
697
|
+
const { locale } = Route.useParams();
|
|
698
|
+
|
|
699
|
+
return (
|
|
700
|
+
<IntlayerProvider locale={locale ?? defaultLocale}>
|
|
701
|
+
<NotFoundComponent />
|
|
702
|
+
{/* Sertakan LocaleSwitcher agar pengguna dapat mengubah bahasa bahkan di 404 */}
|
|
703
|
+
<LocaleSwitcher />
|
|
704
|
+
</IntlayerProvider>
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
```tsx fileName="src/routes/{-$locale}/$.tsx"
|
|
710
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
711
|
+
|
|
712
|
+
import { NotFoundComponent } from "./404";
|
|
713
|
+
|
|
714
|
+
// Rute $ (splat/catch-all) cocok dengan jalur apa pun yang tidak cocok dengan rute lain
|
|
715
|
+
// misalnya, /en/beberapa/jalur/bersarang/mendalam/tidak-valid
|
|
716
|
+
// Ini memastikan SEMUA jalur yang tidak cocok dalam locale menampilkan halaman 404
|
|
717
|
+
// Tanpa ini, jalur dalam yang tidak cocok mungkin menampilkan halaman kosong atau kesalahan
|
|
718
|
+
export const Route = createFileRoute("/{-$locale}/$")({
|
|
719
|
+
component: NotFoundComponent,
|
|
720
|
+
});
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
---
|
|
724
|
+
|
|
725
|
+
### Langkah 15: Konfigurasi TypeScript (Opsional)
|
|
596
726
|
|
|
597
727
|
Intlayer menggunakan module augmentation untuk mendapatkan manfaat dari TypeScript dan membuat codebase Anda lebih kuat.
|
|
598
728
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2024-03-07
|
|
3
|
-
updatedAt:
|
|
3
|
+
updatedAt: 2025-12-10
|
|
4
4
|
title: Cara menerjemahkan aplikasi Vite dan React Anda – panduan i18n 2025
|
|
5
5
|
description: Pelajari cara menambahkan internasionalisasi (i18n) ke aplikasi Vite dan React Anda menggunakan Intlayer. Ikuti panduan ini untuk membuat aplikasi Anda multibahasa.
|
|
6
6
|
keywords:
|
|
@@ -85,10 +85,7 @@ yarn add vite-intlayer --save-dev
|
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
- **intlayer**
|
|
88
|
-
|
|
89
|
-
- **intlayer**
|
|
90
|
-
|
|
91
|
-
Paket inti yang menyediakan alat internasionalisasi untuk manajemen konfigurasi, terjemahan, [deklarasi konten](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/dictionary/content_file.md), transpile, dan [perintah CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/intlayer_cli.md).
|
|
88
|
+
Paket inti yang menyediakan alat internasionalisasi untuk manajemen konfigurasi, terjemahan, [deklarasi konten](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/dictionary/content_file.md), transpile, dan [perintah CLI](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/cli/index.md).
|
|
92
89
|
|
|
93
90
|
- **react-intlayer**
|
|
94
91
|
Paket yang mengintegrasikan Intlayer dengan aplikasi React. Paket ini menyediakan context providers dan hooks untuk internasionalisasi React.
|
|
@@ -1212,7 +1209,7 @@ Dengan menerapkan perubahan ini, aplikasi Anda akan:
|
|
|
1212
1209
|
|
|
1213
1210
|
### (Opsional) Langkah 10: Membuat Komponen Link yang Dilokalkan
|
|
1214
1211
|
|
|
1215
|
-
Untuk memastikan navigasi aplikasi Anda menghormati locale saat ini, Anda dapat membuat komponen `Link` kustom. Komponen ini secara otomatis menambahkan prefix bahasa saat ini pada URL internal, sehingga
|
|
1212
|
+
Untuk memastikan navigasi aplikasi Anda menghormati locale saat ini, Anda dapat membuat komponen `Link` kustom. Komponen ini secara otomatis menambahkan prefix bahasa saat ini pada URL internal, sehingga, misalnya, ketika pengguna berbahasa Prancis mengklik tautan ke halaman "About", mereka akan diarahkan ke `/fr/about` bukan `/about`.
|
|
1216
1213
|
|
|
1217
1214
|
Perilaku ini berguna untuk beberapa alasan:
|
|
1218
1215
|
|
|
@@ -1231,11 +1228,10 @@ import {
|
|
|
1231
1228
|
} from "react";
|
|
1232
1229
|
import { useLocale } from "react-intlayer";
|
|
1233
1230
|
|
|
1234
|
-
export interface LinkProps
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
> {}
|
|
1231
|
+
export interface LinkProps extends DetailedHTMLProps<
|
|
1232
|
+
AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
1233
|
+
HTMLAnchorElement
|
|
1234
|
+
> {}
|
|
1239
1235
|
|
|
1240
1236
|
/**
|
|
1241
1237
|
* Fungsi utilitas untuk memeriksa apakah URL yang diberikan bersifat eksternal.
|
|
@@ -1409,5 +1405,3 @@ Untuk detail lebih lanjut tentang cara menggunakan ekstensi ini, lihat [dokument
|
|
|
1409
1405
|
### Melangkah Lebih Jauh
|
|
1410
1406
|
|
|
1411
1407
|
Untuk melangkah lebih jauh, Anda dapat mengimplementasikan [editor visual](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/intlayer_visual_editor.md) atau mengeksternalisasi konten Anda menggunakan [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/intlayer_CMS.md).
|
|
1412
|
-
|
|
1413
|
-
---
|
|
@@ -22,6 +22,7 @@ slugs:
|
|
|
22
22
|
- doc
|
|
23
23
|
- plugin
|
|
24
24
|
- sync-json
|
|
25
|
+
youtubeVideo: https://www.youtube.com/watch?v=MpGMxniDHNg
|
|
25
26
|
history:
|
|
26
27
|
- version: 6.1.6
|
|
27
28
|
date: 2025-10-05
|
|
@@ -30,6 +31,8 @@ history:
|
|
|
30
31
|
|
|
31
32
|
# Sinkronisasi JSON (jembatan i18n)
|
|
32
33
|
|
|
34
|
+
<iframe title="Cara menjaga terjemahan JSON Anda tetap sinkron dengan 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
|
+
|
|
33
36
|
Gunakan Intlayer sebagai tambahan pada tumpukan i18n Anda yang sudah ada. Plugin ini menjaga pesan JSON Anda tetap sinkron dengan kamus Intlayer sehingga Anda dapat:
|
|
34
37
|
|
|
35
38
|
- Mempertahankan i18next, next-intl, react-intl, vue-i18n, next-translate, nuxt-i18n, Solid-i18next, svelte-i18n, dll.
|
|
@@ -428,7 +428,7 @@ Per cambiare la lingua direttamente dai tuoi componenti, puoi usare il metodo `s
|
|
|
428
428
|
```tsx fileName="src/components/LocaleSwitcher.tsx"
|
|
429
429
|
import { type FC } from "react";
|
|
430
430
|
import { getLocaleName } from "intlayer";
|
|
431
|
-
import { useLocale } from "intlayer";
|
|
431
|
+
import { useLocale } from "react-intlayer";
|
|
432
432
|
|
|
433
433
|
export const LocaleSwitcher: FC = () => {
|
|
434
434
|
const { setLocale, availableLocales, locale } = useLocale();
|
|
@@ -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
|
|