@intlayer/docs 7.5.5 → 7.5.7
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 +4 -4
- package/blog/ar/intlayer_with_next-i18next.md +4 -4
- package/blog/ar/intlayer_with_next-intl.md +4 -4
- package/blog/ar/intlayer_with_react-i18next.md +4 -4
- package/blog/ar/intlayer_with_react-intl.md +4 -4
- package/blog/ar/intlayer_with_vue-i18n.md +4 -4
- package/blog/de/intlayer_with_i18next.md +4 -4
- package/blog/de/intlayer_with_next-i18next.md +4 -4
- package/blog/de/intlayer_with_next-intl.md +4 -4
- package/blog/de/intlayer_with_react-i18next.md +4 -4
- package/blog/de/intlayer_with_react-intl.md +4 -4
- package/blog/de/intlayer_with_vue-i18n.md +4 -4
- package/blog/en/intlayer_with_i18next.md +4 -4
- package/blog/en/intlayer_with_next-i18next.md +4 -4
- package/blog/en/intlayer_with_next-intl.md +4 -4
- package/blog/en/intlayer_with_react-i18next.md +4 -4
- package/blog/en/intlayer_with_react-intl.md +4 -4
- package/blog/en/intlayer_with_vue-i18n.md +4 -4
- package/blog/en-GB/intlayer_with_i18next.md +4 -4
- package/blog/en-GB/intlayer_with_next-i18next.md +4 -4
- package/blog/en-GB/intlayer_with_next-intl.md +4 -4
- package/blog/en-GB/intlayer_with_react-i18next.md +4 -4
- package/blog/en-GB/intlayer_with_react-intl.md +4 -4
- package/blog/en-GB/intlayer_with_vue-i18n.md +4 -4
- package/blog/es/intlayer_with_i18next.md +4 -4
- package/blog/es/intlayer_with_next-i18next.md +4 -4
- package/blog/es/intlayer_with_next-intl.md +4 -4
- package/blog/es/intlayer_with_react-i18next.md +4 -4
- package/blog/es/intlayer_with_react-intl.md +4 -4
- package/blog/es/intlayer_with_vue-i18n.md +4 -4
- package/blog/fr/intlayer_with_i18next.md +4 -4
- package/blog/fr/intlayer_with_next-i18next.md +4 -4
- package/blog/fr/intlayer_with_next-intl.md +4 -4
- package/blog/fr/intlayer_with_react-i18next.md +4 -4
- package/blog/fr/intlayer_with_react-intl.md +4 -4
- package/blog/fr/intlayer_with_vue-i18n.md +4 -4
- package/blog/hi/intlayer_with_i18next.md +4 -4
- package/blog/hi/intlayer_with_next-i18next.md +4 -4
- package/blog/hi/intlayer_with_next-intl.md +4 -4
- package/blog/hi/intlayer_with_react-i18next.md +4 -4
- package/blog/hi/intlayer_with_react-intl.md +4 -4
- package/blog/hi/intlayer_with_vue-i18n.md +4 -4
- package/blog/id/intlayer_with_i18next.md +4 -4
- package/blog/id/intlayer_with_next-i18next.md +4 -4
- package/blog/id/intlayer_with_next-intl.md +4 -4
- package/blog/id/intlayer_with_react-i18next.md +4 -4
- package/blog/id/intlayer_with_react-intl.md +4 -4
- package/blog/id/intlayer_with_vue-i18n.md +4 -4
- package/blog/it/intlayer_with_i18next.md +4 -4
- package/blog/it/intlayer_with_next-i18next.md +4 -4
- package/blog/it/intlayer_with_next-intl.md +4 -4
- package/blog/it/intlayer_with_react-i18next.md +4 -4
- package/blog/it/intlayer_with_react-intl.md +4 -4
- package/blog/it/intlayer_with_vue-i18n.md +4 -4
- package/blog/ja/intlayer_with_i18next.md +4 -4
- package/blog/ja/intlayer_with_next-i18next.md +4 -4
- package/blog/ja/intlayer_with_next-intl.md +4 -4
- package/blog/ja/intlayer_with_react-i18next.md +4 -4
- package/blog/ja/intlayer_with_react-intl.md +4 -4
- package/blog/ja/intlayer_with_vue-i18n.md +4 -4
- package/blog/ko/intlayer_with_i18next.md +4 -4
- package/blog/ko/intlayer_with_next-i18next.md +4 -4
- package/blog/ko/intlayer_with_next-intl.md +4 -4
- package/blog/ko/intlayer_with_react-i18next.md +4 -4
- package/blog/ko/intlayer_with_react-intl.md +4 -4
- package/blog/ko/intlayer_with_vue-i18n.md +4 -4
- package/blog/pl/intlayer_with_i18next.md +4 -4
- package/blog/pl/intlayer_with_next-i18next.md +4 -4
- package/blog/pl/intlayer_with_next-intl.md +4 -4
- package/blog/pl/intlayer_with_react-i18next.md +4 -4
- package/blog/pl/intlayer_with_react-intl.md +4 -4
- package/blog/pl/intlayer_with_vue-i18n.md +4 -4
- package/blog/pt/intlayer_with_i18next.md +4 -4
- package/blog/pt/intlayer_with_next-i18next.md +4 -4
- package/blog/pt/intlayer_with_next-intl.md +4 -4
- package/blog/pt/intlayer_with_react-i18next.md +4 -4
- package/blog/pt/intlayer_with_react-intl.md +4 -4
- package/blog/pt/intlayer_with_vue-i18n.md +4 -4
- package/blog/ru/intlayer_with_i18next.md +4 -4
- package/blog/ru/intlayer_with_next-i18next.md +4 -4
- package/blog/ru/intlayer_with_next-intl.md +4 -4
- package/blog/ru/intlayer_with_react-i18next.md +4 -4
- package/blog/ru/intlayer_with_react-intl.md +4 -4
- package/blog/ru/intlayer_with_vue-i18n.md +4 -4
- package/blog/tr/intlayer_with_i18next.md +4 -4
- package/blog/tr/intlayer_with_next-i18next.md +4 -4
- package/blog/tr/intlayer_with_next-intl.md +4 -4
- package/blog/tr/intlayer_with_react-i18next.md +4 -4
- package/blog/tr/intlayer_with_react-intl.md +8 -4
- package/blog/tr/intlayer_with_vue-i18n.md +4 -4
- package/blog/vi/intlayer_with_i18next.md +4 -4
- package/blog/vi/intlayer_with_next-i18next.md +4 -4
- package/blog/vi/intlayer_with_next-intl.md +4 -4
- package/blog/vi/intlayer_with_react-i18next.md +4 -4
- package/blog/vi/intlayer_with_react-intl.md +4 -4
- package/blog/vi/intlayer_with_vue-i18n.md +4 -4
- package/blog/zh/intlayer_with_i18next.md +4 -4
- package/blog/zh/intlayer_with_next-i18next.md +4 -4
- package/blog/zh/intlayer_with_next-intl.md +4 -4
- package/blog/zh/intlayer_with_react-i18next.md +4 -4
- package/blog/zh/intlayer_with_react-intl.md +4 -4
- package/blog/zh/intlayer_with_vue-i18n.md +4 -4
- package/docs/ar/intlayer_with_next-i18next.md +3 -3
- package/docs/ar/intlayer_with_next-intl.md +3 -3
- package/docs/ar/intlayer_with_react_router_v7.md +72 -16
- package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/de/intlayer_with_next-i18next.md +3 -3
- package/docs/de/intlayer_with_next-intl.md +3 -3
- package/docs/de/intlayer_with_react_router_v7.md +72 -15
- package/docs/de/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/en/configuration.md +1 -0
- package/docs/en/intlayer_with_next-i18next.md +3 -3
- package/docs/en/intlayer_with_next-intl.md +3 -3
- package/docs/en/intlayer_with_react_router_v7.md +74 -15
- package/docs/en/intlayer_with_react_router_v7_fs_routes.md +98 -19
- package/docs/en-GB/configuration.md +1 -0
- package/docs/en-GB/intlayer_with_next-i18next.md +3 -3
- package/docs/en-GB/intlayer_with_next-intl.md +3 -3
- package/docs/en-GB/intlayer_with_react_router_v7.md +73 -16
- package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/es/intlayer_with_next-i18next.md +3 -3
- package/docs/es/intlayer_with_next-intl.md +3 -3
- package/docs/es/intlayer_with_react_router_v7.md +72 -15
- package/docs/es/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/fr/intlayer_with_next-i18next.md +3 -3
- package/docs/fr/intlayer_with_next-intl.md +3 -3
- package/docs/fr/intlayer_with_react_router_v7.md +72 -15
- package/docs/fr/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/hi/intlayer_with_next-i18next.md +3 -3
- package/docs/hi/intlayer_with_next-intl.md +3 -3
- package/docs/hi/intlayer_with_react_router_v7.md +72 -16
- package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/id/intlayer_with_next-i18next.md +3 -3
- package/docs/id/intlayer_with_next-intl.md +3 -3
- package/docs/id/intlayer_with_react_router_v7.md +72 -15
- package/docs/id/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/it/intlayer_with_next-i18next.md +3 -3
- package/docs/it/intlayer_with_next-intl.md +3 -3
- package/docs/it/intlayer_with_react_router_v7.md +72 -15
- package/docs/it/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/ja/intlayer_with_next-i18next.md +3 -3
- package/docs/ja/intlayer_with_next-intl.md +3 -3
- package/docs/ja/intlayer_with_react_router_v7.md +72 -15
- package/docs/ja/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/ko/intlayer_with_next-i18next.md +3 -3
- package/docs/ko/intlayer_with_next-intl.md +3 -3
- package/docs/ko/intlayer_with_react_router_v7.md +72 -15
- package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/pl/intlayer_with_next-i18next.md +3 -3
- package/docs/pl/intlayer_with_next-intl.md +3 -3
- package/docs/pl/intlayer_with_react_router_v7.md +45 -13
- package/docs/pl/intlayer_with_react_router_v7_fs_routes.md +94 -18
- package/docs/pt/intlayer_with_next-i18next.md +3 -3
- package/docs/pt/intlayer_with_next-intl.md +3 -3
- package/docs/pt/intlayer_with_react_router_v7.md +79 -46
- package/docs/pt/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/ru/intlayer_with_next-i18next.md +3 -3
- package/docs/ru/intlayer_with_next-intl.md +3 -3
- package/docs/ru/intlayer_with_react_router_v7.md +72 -15
- package/docs/ru/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/tr/intlayer_with_next-i18next.md +3 -3
- package/docs/tr/intlayer_with_next-intl.md +3 -3
- package/docs/tr/intlayer_with_react_router_v7.md +72 -15
- package/docs/tr/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/vi/intlayer_with_next-i18next.md +3 -3
- package/docs/vi/intlayer_with_next-intl.md +3 -3
- package/docs/vi/intlayer_with_react_router_v7.md +72 -15
- package/docs/vi/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/zh/intlayer_with_next-i18next.md +3 -3
- package/docs/zh/intlayer_with_next-intl.md +3 -3
- package/docs/zh/intlayer_with_react_router_v7.md +72 -15
- package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-09-04
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-27
|
|
4
4
|
title: كيفية ترجمة تطبيق React Router v7 – دليل i18n 2025
|
|
5
5
|
description: تعلّم كيفية إضافة التدويل (i18n) إلى تطبيق React Router v7 الخاص بك باستخدام Intlayer. اتبع هذا الدليل الشامل لجعل تطبيقك متعدد اللغات مع توجيه يدعم اللغة المحلية.
|
|
6
6
|
keywords:
|
|
@@ -20,6 +20,9 @@ slugs:
|
|
|
20
20
|
applicationTemplate: https://github.com/aymericzip/intlayer-react-router-v7-template
|
|
21
21
|
youtubeVideo: https://www.youtube.com/watch?v=dS9L7uJeak4
|
|
22
22
|
history:
|
|
23
|
+
- version: 7.5.6
|
|
24
|
+
date: 2025-12-27
|
|
25
|
+
changes: تحديث التخطيط ومعالجة 404
|
|
23
26
|
- version: 6.1.5
|
|
24
27
|
date: 2025-10-03
|
|
25
28
|
changes: تحديث الوثيقة
|
|
@@ -168,14 +171,11 @@ export default defineConfig({
|
|
|
168
171
|
قم بإعداد تكوين التوجيه الخاص بك مع مسارات مدركة للغة:
|
|
169
172
|
|
|
170
173
|
```typescript fileName="app/routes.ts"
|
|
171
|
-
typescript fileName="app/routes.ts"
|
|
172
174
|
import { layout, route, type RouteConfig } from "@react-router/dev/routes";
|
|
173
175
|
|
|
174
176
|
export default [
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
route("/:lang?/about", "routes/about/page.tsx"), // صفحة حول المحلية
|
|
178
|
-
]),
|
|
177
|
+
route("/:lang?", "routes/page.tsx"), // الصفحة الرئيسية المحلية
|
|
178
|
+
route("/:lang?/about", "routes/about/page.tsx"), // صفحة حول المحلية
|
|
179
179
|
] satisfies RouteConfig;
|
|
180
180
|
```
|
|
181
181
|
|
|
@@ -185,19 +185,50 @@ export default [
|
|
|
185
185
|
|
|
186
186
|
#### التخطيط الجذري
|
|
187
187
|
|
|
188
|
-
```tsx fileName="app/
|
|
188
|
+
```tsx fileName="app/root.tsx"
|
|
189
|
+
import { getLocaleFromPath } from "intlayer";
|
|
189
190
|
import { IntlayerProvider } from "react-intlayer";
|
|
190
|
-
import {
|
|
191
|
+
import {
|
|
192
|
+
data,
|
|
193
|
+
Meta,
|
|
194
|
+
Scripts,
|
|
195
|
+
ScrollRestoration,
|
|
196
|
+
useLoaderData,
|
|
197
|
+
} from "react-router";
|
|
198
|
+
import type { Route } from "./+types/root";
|
|
191
199
|
|
|
192
|
-
|
|
200
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
193
201
|
|
|
194
|
-
export
|
|
195
|
-
const
|
|
202
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
203
|
+
const locale = getLocaleFromPath(request.url);
|
|
204
|
+
|
|
205
|
+
if (!locale) {
|
|
206
|
+
throw data("Language not supported", { status: 404 });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return { locale };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function Layout({
|
|
213
|
+
children,
|
|
214
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
215
|
+
const data = useLoaderData<typeof loader>();
|
|
216
|
+
const { locale } = data ?? {};
|
|
196
217
|
|
|
197
218
|
return (
|
|
198
|
-
<
|
|
199
|
-
<
|
|
200
|
-
|
|
219
|
+
<html lang={locale}>
|
|
220
|
+
<head>
|
|
221
|
+
<meta charSet="utf-8" />
|
|
222
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
223
|
+
<Meta />
|
|
224
|
+
<Links />
|
|
225
|
+
</head>
|
|
226
|
+
<body>
|
|
227
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
228
|
+
<ScrollRestoration />
|
|
229
|
+
<Scripts />
|
|
230
|
+
</body>
|
|
231
|
+
</html>
|
|
201
232
|
);
|
|
202
233
|
}
|
|
203
234
|
```
|
|
@@ -311,9 +342,34 @@ export const useLocalizedNavigate = () => {
|
|
|
311
342
|
|
|
312
343
|
#### الصفحة الرئيسية المترجمة
|
|
313
344
|
|
|
314
|
-
```tsx fileName="app/routes/
|
|
345
|
+
```tsx fileName="app/routes/page.tsx"
|
|
346
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
315
347
|
import { useIntlayer } from "react-intlayer";
|
|
316
|
-
import {
|
|
348
|
+
import { data } from "react-router";
|
|
349
|
+
|
|
350
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
351
|
+
|
|
352
|
+
import { Navbar } from "~/components/navbar";
|
|
353
|
+
import type { Route } from "./+types/page";
|
|
354
|
+
|
|
355
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
356
|
+
const { locale } = params;
|
|
357
|
+
|
|
358
|
+
const { isValid } = validatePrefix(locale);
|
|
359
|
+
|
|
360
|
+
if (!isValid) {
|
|
361
|
+
throw data("Locale not supported", { status: 404 });
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
366
|
+
const content = getIntlayer("page", params.locale);
|
|
367
|
+
|
|
368
|
+
return [
|
|
369
|
+
{ title: content.title },
|
|
370
|
+
{ content: content.description, name: "description" },
|
|
371
|
+
];
|
|
372
|
+
};
|
|
317
373
|
|
|
318
374
|
export default function Page() {
|
|
319
375
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
@@ -32,6 +32,8 @@ history:
|
|
|
32
32
|
|
|
33
33
|
يوضح هذا الدليل كيفية دمج **Intlayer** لتحقيق التدويل السلس في مشاريع React Router v7 مع توجيه يدعم اللغة المحلية، ودعم TypeScript، وممارسات تطوير حديثة.
|
|
34
34
|
|
|
35
|
+
للحصول على التوجيه من جانب العميل، راجع دليل [Intlayer مع React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ar/intlayer_with_react_router_v7.md).
|
|
36
|
+
|
|
35
37
|
## Table of Contents
|
|
36
38
|
|
|
37
39
|
<TOC/>
|
|
@@ -552,15 +552,15 @@ Intlayer hilft Ihnen, JSON-Übersetzungen synchron zu halten, auf fehlende Schl
|
|
|
552
552
|
Installieren Sie die Intlayer-Abhängigkeiten:
|
|
553
553
|
|
|
554
554
|
```bash packageManager="npm"
|
|
555
|
-
npm install intlayer @intlayer/sync-json-plugin
|
|
555
|
+
npm install intlayer @intlayer/sync-json-plugin --save-dev
|
|
556
556
|
```
|
|
557
557
|
|
|
558
558
|
```bash packageManager="pnpm"
|
|
559
|
-
pnpm add intlayer @intlayer/sync-json-plugin
|
|
559
|
+
pnpm add intlayer @intlayer/sync-json-plugin --save-dev
|
|
560
560
|
```
|
|
561
561
|
|
|
562
562
|
```bash packageManager="yarn"
|
|
563
|
-
yarn add intlayer @intlayer/sync-json-plugin
|
|
563
|
+
yarn add intlayer @intlayer/sync-json-plugin --dev
|
|
564
564
|
```
|
|
565
565
|
|
|
566
566
|
```ts fileName="intlayer.config.ts"
|
|
@@ -391,15 +391,15 @@ export const config = {
|
|
|
391
391
|
Installieren Sie die Intlayer-Abhängigkeiten:
|
|
392
392
|
|
|
393
393
|
```bash packageManager="npm"
|
|
394
|
-
npm install intlayer @intlayer/sync-json-plugin
|
|
394
|
+
npm install intlayer @intlayer/sync-json-plugin --save-dev
|
|
395
395
|
```
|
|
396
396
|
|
|
397
397
|
```bash packageManager="yarn"
|
|
398
|
-
yarn add intlayer @intlayer/sync-json-plugin
|
|
398
|
+
yarn add intlayer @intlayer/sync-json-plugin --dev
|
|
399
399
|
```
|
|
400
400
|
|
|
401
401
|
```bash packageManager="pnpm"
|
|
402
|
-
pnpm add intlayer @intlayer/sync-json-plugin
|
|
402
|
+
pnpm add intlayer @intlayer/sync-json-plugin --save-dev
|
|
403
403
|
```
|
|
404
404
|
|
|
405
405
|
Erstellen Sie die Intlayer-Konfigurationsdatei:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-09-04
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-27
|
|
4
4
|
title: Wie Sie Ihre React Router v7 übersetzen – i18n-Leitfaden 2025
|
|
5
5
|
description: Erfahren Sie, wie Sie Internationalisierung (i18n) zu Ihrer React Router v7-Anwendung mit Intlayer hinzufügen. Folgen Sie dieser umfassenden Anleitung, um Ihre App mehrsprachig mit lokalisierungsbewusstem Routing zu machen.
|
|
6
6
|
keywords:
|
|
@@ -20,6 +20,9 @@ slugs:
|
|
|
20
20
|
applicationTemplate: https://github.com/aymericzip/intlayer-react-router-v7-template
|
|
21
21
|
youtubeVideo: https://www.youtube.com/watch?v=dS9L7uJeak4
|
|
22
22
|
history:
|
|
23
|
+
- version: 7.5.6
|
|
24
|
+
date: 2025-12-27
|
|
25
|
+
changes: Layout aktualisieren und 404 behandeln
|
|
23
26
|
- version: 6.1.5
|
|
24
27
|
date: 2025-10-03
|
|
25
28
|
changes: Dokumentation aktualisiert
|
|
@@ -173,10 +176,8 @@ Richten Sie Ihre Routing-Konfiguration mit sprachsensitiven Routen ein:
|
|
|
173
176
|
import { layout, route, type RouteConfig } from "@react-router/dev/routes";
|
|
174
177
|
|
|
175
178
|
export default [
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
route("/:lang?/about", "routes/about/page.tsx"), // Lokalisierte Über-Seite
|
|
179
|
-
]),
|
|
179
|
+
route("/:lang?", "routes/page.tsx"), // Lokalisierte Startseite
|
|
180
|
+
route("/:lang?/about", "routes/about/page.tsx"), // Lokalisierte Über-Seite
|
|
180
181
|
] satisfies RouteConfig;
|
|
181
182
|
```
|
|
182
183
|
|
|
@@ -186,19 +187,50 @@ Richten Sie Ihr Root-Layout und sprachspezifische Layouts ein:
|
|
|
186
187
|
|
|
187
188
|
#### Root-Layout
|
|
188
189
|
|
|
189
|
-
```tsx fileName="app/
|
|
190
|
+
```tsx fileName="app/root.tsx"
|
|
191
|
+
import { getLocaleFromPath } from "intlayer";
|
|
190
192
|
import { IntlayerProvider } from "react-intlayer";
|
|
191
|
-
import {
|
|
193
|
+
import {
|
|
194
|
+
data,
|
|
195
|
+
Meta,
|
|
196
|
+
Scripts,
|
|
197
|
+
ScrollRestoration,
|
|
198
|
+
useLoaderData,
|
|
199
|
+
} from "react-router";
|
|
200
|
+
import type { Route } from "./+types/root";
|
|
192
201
|
|
|
193
|
-
|
|
202
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
194
203
|
|
|
195
|
-
export
|
|
196
|
-
const
|
|
204
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
205
|
+
const locale = getLocaleFromPath(request.url);
|
|
206
|
+
|
|
207
|
+
if (!locale) {
|
|
208
|
+
throw data("Language not supported", { status: 404 });
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return { locale };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function Layout({
|
|
215
|
+
children,
|
|
216
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
217
|
+
const data = useLoaderData<typeof loader>();
|
|
218
|
+
const { locale } = data ?? {};
|
|
197
219
|
|
|
198
220
|
return (
|
|
199
|
-
<
|
|
200
|
-
<
|
|
201
|
-
|
|
221
|
+
<html lang={locale}>
|
|
222
|
+
<head>
|
|
223
|
+
<meta charSet="utf-8" />
|
|
224
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
225
|
+
<Meta />
|
|
226
|
+
<Links />
|
|
227
|
+
</head>
|
|
228
|
+
<body>
|
|
229
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
230
|
+
<ScrollRestoration />
|
|
231
|
+
<Scripts />
|
|
232
|
+
</body>
|
|
233
|
+
</html>
|
|
202
234
|
);
|
|
203
235
|
}
|
|
204
236
|
```
|
|
@@ -312,9 +344,34 @@ Greifen Sie in Ihrer gesamten Anwendung auf Ihre Inhaltswörterbücher zu:
|
|
|
312
344
|
|
|
313
345
|
#### Lokalisierte Startseite
|
|
314
346
|
|
|
315
|
-
```tsx fileName="app/routes/
|
|
347
|
+
```tsx fileName="app/routes/page.tsx"
|
|
348
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
316
349
|
import { useIntlayer } from "react-intlayer";
|
|
317
|
-
import {
|
|
350
|
+
import { data } from "react-router";
|
|
351
|
+
|
|
352
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
353
|
+
|
|
354
|
+
import { Navbar } from "~/components/navbar";
|
|
355
|
+
import type { Route } from "./+types/page";
|
|
356
|
+
|
|
357
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
358
|
+
const { locale } = params;
|
|
359
|
+
|
|
360
|
+
const { isValid } = validatePrefix(locale);
|
|
361
|
+
|
|
362
|
+
if (!isValid) {
|
|
363
|
+
throw data("Locale not supported", { status: 404 });
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
368
|
+
const content = getIntlayer("page", params.locale);
|
|
369
|
+
|
|
370
|
+
return [
|
|
371
|
+
{ title: content.title },
|
|
372
|
+
{ content: content.description, name: "description" },
|
|
373
|
+
];
|
|
374
|
+
};
|
|
318
375
|
|
|
319
376
|
export default function Page() {
|
|
320
377
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
@@ -31,6 +31,8 @@ history:
|
|
|
31
31
|
|
|
32
32
|
Diese Anleitung zeigt, wie Sie **Intlayer** für nahtlose Internationalisierung in React Router v7-Projekten mit **dateisystembasiertem Routing** (`@react-router/fs-routes`) mit lokalisierungsbewusstem Routing, TypeScript-Unterstützung und modernen Entwicklungsmethoden integrieren.
|
|
33
33
|
|
|
34
|
+
Für clientseitiges Routing lesen Sie bitte die Anleitung [Intlayer mit React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/intlayer_with_react_router_v7.md).
|
|
35
|
+
|
|
34
36
|
## Table of Contents
|
|
35
37
|
|
|
36
38
|
<TOC/>
|
|
@@ -197,12 +199,13 @@ Erstellen Sie die folgenden Dateien in Ihrem Verzeichnis `app/routes/`:
|
|
|
197
199
|
#### Dateistruktur
|
|
198
200
|
|
|
199
201
|
```bash
|
|
200
|
-
app/
|
|
201
|
-
├──
|
|
202
|
-
|
|
203
|
-
├── ($locale)._index.
|
|
204
|
-
├── ($locale).
|
|
205
|
-
|
|
202
|
+
app/
|
|
203
|
+
├── root.tsx # Layout-Wrapper für Locale-Routen
|
|
204
|
+
└──routes/
|
|
205
|
+
├── ($locale)._index.tsx # Startseite (/, /es, etc.)
|
|
206
|
+
├── ($locale)._index.content.ts # Startseiten-Inhalt
|
|
207
|
+
├── ($locale).about.tsx # Über-Seite (/about, /es/about, etc.)
|
|
208
|
+
└── ($locale).about.content.ts # Über-Seiten-Inhalt
|
|
206
209
|
```
|
|
207
210
|
|
|
208
211
|
Die Namenskonventionen:
|
|
@@ -214,23 +217,50 @@ Die Namenskonventionen:
|
|
|
214
217
|
|
|
215
218
|
#### Layout-Komponente
|
|
216
219
|
|
|
217
|
-
```tsx fileName="app/
|
|
220
|
+
```tsx fileName="app/root.tsx"
|
|
221
|
+
import { getLocaleFromPath } from "intlayer";
|
|
218
222
|
import { IntlayerProvider } from "react-intlayer";
|
|
219
|
-
import {
|
|
223
|
+
import {
|
|
224
|
+
isRouteErrorResponse,
|
|
225
|
+
Meta,
|
|
226
|
+
Outlet,
|
|
227
|
+
Scripts,
|
|
228
|
+
ScrollRestoration,
|
|
229
|
+
useLoaderData,
|
|
230
|
+
} from "react-router";
|
|
220
231
|
|
|
221
|
-
import {
|
|
232
|
+
import type { Route } from "./+types/root";
|
|
222
233
|
|
|
223
|
-
import
|
|
234
|
+
import "./app.css";
|
|
224
235
|
|
|
225
|
-
|
|
226
|
-
useI18nHTMLAttributes();
|
|
236
|
+
// links and ErrorBoundary code
|
|
227
237
|
|
|
228
|
-
|
|
238
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
239
|
+
const locale = getLocaleFromPath(request.url);
|
|
240
|
+
|
|
241
|
+
return { locale };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function Layout({
|
|
245
|
+
children,
|
|
246
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
247
|
+
const data = useLoaderData<typeof loader>();
|
|
248
|
+
const { locale } = data ?? {};
|
|
229
249
|
|
|
230
250
|
return (
|
|
231
|
-
<
|
|
232
|
-
<
|
|
233
|
-
|
|
251
|
+
<html lang={locale}>
|
|
252
|
+
<head>
|
|
253
|
+
<meta charSet="utf-8" />
|
|
254
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
255
|
+
<Meta />
|
|
256
|
+
<Links />
|
|
257
|
+
</head>
|
|
258
|
+
<body>
|
|
259
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
260
|
+
<ScrollRestoration />
|
|
261
|
+
<Scripts />
|
|
262
|
+
</body>
|
|
263
|
+
</html>
|
|
234
264
|
);
|
|
235
265
|
}
|
|
236
266
|
```
|
|
@@ -238,11 +268,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
|
|
|
238
268
|
#### Index-Seite
|
|
239
269
|
|
|
240
270
|
```tsx fileName="app/routes/($locale)._index.tsx"
|
|
271
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
241
272
|
import { useIntlayer } from "react-intlayer";
|
|
242
|
-
import {
|
|
273
|
+
import { data } from "react-router";
|
|
274
|
+
|
|
275
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
276
|
+
import { Navbar } from "~/components/navbar";
|
|
243
277
|
|
|
244
278
|
import type { Route } from "./+types/($locale)._index";
|
|
245
279
|
|
|
280
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
281
|
+
const { locale } = params;
|
|
282
|
+
|
|
283
|
+
const { isValid } = validatePrefix(locale);
|
|
284
|
+
|
|
285
|
+
if (!isValid) {
|
|
286
|
+
throw data("Locale not supported", { status: 404 });
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
291
|
+
const content = getIntlayer("page", params.locale);
|
|
292
|
+
|
|
293
|
+
return [
|
|
294
|
+
{ title: content.title },
|
|
295
|
+
{ content: content.description, name: "description" },
|
|
296
|
+
];
|
|
297
|
+
};
|
|
298
|
+
|
|
246
299
|
export default function Page() {
|
|
247
300
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
248
301
|
|
|
@@ -261,11 +314,34 @@ export default function Page() {
|
|
|
261
314
|
#### Über-Seite
|
|
262
315
|
|
|
263
316
|
```tsx fileName="app/routes/($locale).about.tsx"
|
|
317
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
264
318
|
import { useIntlayer } from "react-intlayer";
|
|
265
|
-
import {
|
|
319
|
+
import { data } from "react-router";
|
|
320
|
+
|
|
321
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
322
|
+
import { Navbar } from "~/components/navbar";
|
|
266
323
|
|
|
267
324
|
import type { Route } from "./+types/($locale).about";
|
|
268
325
|
|
|
326
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
327
|
+
const { locale } = params;
|
|
328
|
+
|
|
329
|
+
const { isValid } = validatePrefix(locale);
|
|
330
|
+
|
|
331
|
+
if (!isValid) {
|
|
332
|
+
throw data("Locale not supported", { status: 404 });
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
337
|
+
const content = getIntlayer("about", params.locale);
|
|
338
|
+
|
|
339
|
+
return [
|
|
340
|
+
{ title: content.title },
|
|
341
|
+
{ content: content.description, name: "description" },
|
|
342
|
+
];
|
|
343
|
+
};
|
|
344
|
+
|
|
269
345
|
export default function AboutPage() {
|
|
270
346
|
const { title, content, homeLink } = useIntlayer("about");
|
|
271
347
|
|
|
@@ -486,7 +562,7 @@ export const useI18nHTMLAttributes = () => {
|
|
|
486
562
|
};
|
|
487
563
|
```
|
|
488
564
|
|
|
489
|
-
Dieser Hook wird bereits in der Layout-Komponente (`
|
|
565
|
+
Dieser Hook wird bereits in der Layout-Komponente (`root.tsx`) verwendet, die in Schritt 5 gezeigt wird.
|
|
490
566
|
|
|
491
567
|
### Schritt 10: Middleware hinzufügen (Optional)
|
|
492
568
|
|
package/docs/en/configuration.md
CHANGED
|
@@ -552,15 +552,15 @@ Intlayer helps you keep JSON translations in sync, test for missing keys, and fi
|
|
|
552
552
|
Install the intlayer dependencies:
|
|
553
553
|
|
|
554
554
|
```bash packageManager="npm"
|
|
555
|
-
npm install intlayer @intlayer/sync-json-plugin
|
|
555
|
+
npm install intlayer @intlayer/sync-json-plugin --save-dev
|
|
556
556
|
```
|
|
557
557
|
|
|
558
558
|
```bash packageManager="pnpm"
|
|
559
|
-
pnpm add intlayer @intlayer/sync-json-plugin
|
|
559
|
+
pnpm add intlayer @intlayer/sync-json-plugin --save-dev
|
|
560
560
|
```
|
|
561
561
|
|
|
562
562
|
```bash packageManager="yarn"
|
|
563
|
-
yarn add intlayer @intlayer/sync-json-plugin
|
|
563
|
+
yarn add intlayer @intlayer/sync-json-plugin --dev
|
|
564
564
|
```
|
|
565
565
|
|
|
566
566
|
```ts fileName="intlayer.config.ts"
|
|
@@ -391,15 +391,15 @@ export const config = {
|
|
|
391
391
|
Install the intlayer dependencies:
|
|
392
392
|
|
|
393
393
|
```bash packageManager="npm"
|
|
394
|
-
npm install intlayer @intlayer/sync-json-plugin
|
|
394
|
+
npm install intlayer @intlayer/sync-json-plugin --save-dev
|
|
395
395
|
```
|
|
396
396
|
|
|
397
397
|
```bash packageManager="yarn"
|
|
398
|
-
yarn add intlayer @intlayer/sync-json-plugin
|
|
398
|
+
yarn add intlayer @intlayer/sync-json-plugin --dev
|
|
399
399
|
```
|
|
400
400
|
|
|
401
401
|
```bash packageManager="pnpm"
|
|
402
|
-
pnpm add intlayer @intlayer/sync-json-plugin
|
|
402
|
+
pnpm add intlayer @intlayer/sync-json-plugin --save-dev
|
|
403
403
|
```
|
|
404
404
|
|
|
405
405
|
Create the intlayer configuration file:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-09-04
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-27
|
|
4
4
|
title: How to translate your React Router v7 app – i18n guide 2025
|
|
5
5
|
description: Learn how to add internationalization (i18n) to your React Router v7 application using Intlayer. Follow this comprehensive guide to make your app multilingual with locale-aware routing.
|
|
6
6
|
keywords:
|
|
@@ -20,6 +20,9 @@ slugs:
|
|
|
20
20
|
applicationTemplate: https://github.com/aymericzip/intlayer-react-router-v7-template
|
|
21
21
|
youtubeVideo: https://www.youtube.com/watch?v=dS9L7uJeak4
|
|
22
22
|
history:
|
|
23
|
+
- version: 7.5.6
|
|
24
|
+
date: 2025-12-27
|
|
25
|
+
changes: Update Layout and handle 404
|
|
23
26
|
- version: 6.1.5
|
|
24
27
|
date: 2025-10-03
|
|
25
28
|
changes: Updated doc
|
|
@@ -32,6 +35,8 @@ history:
|
|
|
32
35
|
|
|
33
36
|
This guide demonstrates how to integrate **Intlayer** for seamless internationalization in React Router v7 projects with locale-aware routing, TypeScript support, and modern development practices.
|
|
34
37
|
|
|
38
|
+
This guide focuses on frontend routing. For fs-routes routing, refer to the [Intlayer with React Router v7 File-System Routes](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_react_router_v7_fs_routes.md) guide.
|
|
39
|
+
|
|
35
40
|
## Table of Contents
|
|
36
41
|
|
|
37
42
|
<TOC/>
|
|
@@ -179,10 +184,8 @@ Set up your routing configuration with locale-aware routes:
|
|
|
179
184
|
import { layout, route, type RouteConfig } from "@react-router/dev/routes";
|
|
180
185
|
|
|
181
186
|
export default [
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
route("/:lang?/about", "routes/about/page.tsx"), // Localized about page
|
|
185
|
-
]),
|
|
187
|
+
route("/:lang?", "routes/page.tsx"), // Localized home page
|
|
188
|
+
route("/:lang?/about", "routes/about/page.tsx"), // Localized about page
|
|
186
189
|
] satisfies RouteConfig;
|
|
187
190
|
```
|
|
188
191
|
|
|
@@ -192,19 +195,50 @@ Set up your root layout and locale-specific layouts:
|
|
|
192
195
|
|
|
193
196
|
#### Root Layout
|
|
194
197
|
|
|
195
|
-
```tsx fileName="app/
|
|
198
|
+
```tsx fileName="app/root.tsx"
|
|
199
|
+
import { getLocaleFromPath } from "intlayer";
|
|
196
200
|
import { IntlayerProvider } from "react-intlayer";
|
|
197
|
-
import {
|
|
201
|
+
import {
|
|
202
|
+
data,
|
|
203
|
+
Meta,
|
|
204
|
+
Scripts,
|
|
205
|
+
ScrollRestoration,
|
|
206
|
+
useLoaderData,
|
|
207
|
+
} from "react-router";
|
|
208
|
+
import type { Route } from "./+types/root";
|
|
198
209
|
|
|
199
|
-
|
|
210
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
200
211
|
|
|
201
|
-
export
|
|
202
|
-
const
|
|
212
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
213
|
+
const locale = getLocaleFromPath(request.url);
|
|
214
|
+
|
|
215
|
+
if (!locale) {
|
|
216
|
+
throw data("Language not supported", { status: 404 });
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return { locale };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function Layout({
|
|
223
|
+
children,
|
|
224
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
225
|
+
const data = useLoaderData<typeof loader>();
|
|
226
|
+
const { locale } = data ?? {};
|
|
203
227
|
|
|
204
228
|
return (
|
|
205
|
-
<
|
|
206
|
-
<
|
|
207
|
-
|
|
229
|
+
<html lang={locale}>
|
|
230
|
+
<head>
|
|
231
|
+
<meta charSet="utf-8" />
|
|
232
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
233
|
+
<Meta />
|
|
234
|
+
<Links />
|
|
235
|
+
</head>
|
|
236
|
+
<body>
|
|
237
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
238
|
+
<ScrollRestoration />
|
|
239
|
+
<Scripts />
|
|
240
|
+
</body>
|
|
241
|
+
</html>
|
|
208
242
|
);
|
|
209
243
|
}
|
|
210
244
|
```
|
|
@@ -316,9 +350,34 @@ Access your content dictionaries throughout your application:
|
|
|
316
350
|
|
|
317
351
|
#### Localized Home Page
|
|
318
352
|
|
|
319
|
-
```tsx fileName="app/routes/
|
|
353
|
+
```tsx fileName="app/routes/page.tsx"
|
|
354
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
320
355
|
import { useIntlayer } from "react-intlayer";
|
|
321
|
-
import {
|
|
356
|
+
import { data } from "react-router";
|
|
357
|
+
|
|
358
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
359
|
+
|
|
360
|
+
import { Navbar } from "~/components/navbar";
|
|
361
|
+
import type { Route } from "./+types/page";
|
|
362
|
+
|
|
363
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
364
|
+
const { locale } = params;
|
|
365
|
+
|
|
366
|
+
const { isValid } = validatePrefix(locale);
|
|
367
|
+
|
|
368
|
+
if (!isValid) {
|
|
369
|
+
throw data("Locale not supported", { status: 404 });
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
374
|
+
const content = getIntlayer("page", params.locale);
|
|
375
|
+
|
|
376
|
+
return [
|
|
377
|
+
{ title: content.title },
|
|
378
|
+
{ content: content.description, name: "description" },
|
|
379
|
+
];
|
|
380
|
+
};
|
|
322
381
|
|
|
323
382
|
export default function Page() {
|
|
324
383
|
const { title, description, aboutLink } = useIntlayer("page");
|