@intlayer/docs 7.5.6 → 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 +4 -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
|
@@ -31,6 +31,8 @@ history:
|
|
|
31
31
|
|
|
32
32
|
Esta guía demuestra cómo integrar **Intlayer** para una internacionalización fluida en proyectos con React Router v7 usando **enrutamiento basado en el sistema de archivos** (`@react-router/fs-routes`) con enrutamiento consciente del locale, soporte para TypeScript y prácticas modernas de desarrollo.
|
|
33
33
|
|
|
34
|
+
Para el enrutamiento del lado del cliente, consulte la guía [Intlayer con React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/es/intlayer_with_react_router_v7.md).
|
|
35
|
+
|
|
34
36
|
## Table of Contents
|
|
35
37
|
|
|
36
38
|
<TOC/>
|
|
@@ -198,12 +200,13 @@ Crea los siguientes archivos en tu directorio `app/routes/`:
|
|
|
198
200
|
#### Estructura de archivos
|
|
199
201
|
|
|
200
202
|
```bash
|
|
201
|
-
app/
|
|
202
|
-
├──
|
|
203
|
-
|
|
204
|
-
├── ($locale)._index.
|
|
205
|
-
├── ($locale).
|
|
206
|
-
|
|
203
|
+
app/
|
|
204
|
+
├── root.tsx # Wrapper de layout para rutas de locale
|
|
205
|
+
└──routes/
|
|
206
|
+
├── ($locale)._index.tsx # Página de inicio (/, /es, etc.)
|
|
207
|
+
├── ($locale)._index.content.ts # Contenido de la página de inicio
|
|
208
|
+
├── ($locale).about.tsx # Página Acerca de (/about, /es/about, etc.)
|
|
209
|
+
└── ($locale).about.content.ts # Contenido de la página Acerca de
|
|
207
210
|
```
|
|
208
211
|
|
|
209
212
|
Las convenciones de nomenclatura:
|
|
@@ -215,23 +218,50 @@ Las convenciones de nomenclatura:
|
|
|
215
218
|
|
|
216
219
|
#### Componente de Layout
|
|
217
220
|
|
|
218
|
-
```tsx fileName="app/
|
|
221
|
+
```tsx fileName="app/root.tsx"
|
|
222
|
+
import { getLocaleFromPath } from "intlayer";
|
|
219
223
|
import { IntlayerProvider } from "react-intlayer";
|
|
220
|
-
import {
|
|
224
|
+
import {
|
|
225
|
+
isRouteErrorResponse,
|
|
226
|
+
Meta,
|
|
227
|
+
Outlet,
|
|
228
|
+
Scripts,
|
|
229
|
+
ScrollRestoration,
|
|
230
|
+
useLoaderData,
|
|
231
|
+
} from "react-router";
|
|
221
232
|
|
|
222
|
-
import {
|
|
233
|
+
import type { Route } from "./+types/root";
|
|
223
234
|
|
|
224
|
-
import
|
|
235
|
+
import "./app.css";
|
|
225
236
|
|
|
226
|
-
|
|
227
|
-
useI18nHTMLAttributes();
|
|
237
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
228
238
|
|
|
229
|
-
|
|
239
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
240
|
+
const locale = getLocaleFromPath(request.url);
|
|
241
|
+
|
|
242
|
+
return { locale };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function Layout({
|
|
246
|
+
children,
|
|
247
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
248
|
+
const data = useLoaderData<typeof loader>();
|
|
249
|
+
const { locale } = data ?? {};
|
|
230
250
|
|
|
231
251
|
return (
|
|
232
|
-
<
|
|
233
|
-
<
|
|
234
|
-
|
|
252
|
+
<html lang={locale}>
|
|
253
|
+
<head>
|
|
254
|
+
<meta charSet="utf-8" />
|
|
255
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
256
|
+
<Meta />
|
|
257
|
+
<Links />
|
|
258
|
+
</head>
|
|
259
|
+
<body>
|
|
260
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
261
|
+
<ScrollRestoration />
|
|
262
|
+
<Scripts />
|
|
263
|
+
</body>
|
|
264
|
+
</html>
|
|
235
265
|
);
|
|
236
266
|
}
|
|
237
267
|
```
|
|
@@ -239,11 +269,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
|
|
|
239
269
|
#### Página de índice
|
|
240
270
|
|
|
241
271
|
```tsx fileName="app/routes/($locale)._index.tsx"
|
|
272
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
242
273
|
import { useIntlayer } from "react-intlayer";
|
|
243
|
-
import {
|
|
274
|
+
import { data } from "react-router";
|
|
275
|
+
|
|
276
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
277
|
+
import { Navbar } from "~/components/navbar";
|
|
244
278
|
|
|
245
279
|
import type { Route } from "./+types/($locale)._index";
|
|
246
280
|
|
|
281
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
282
|
+
const { locale } = params;
|
|
283
|
+
|
|
284
|
+
const { isValid } = validatePrefix(locale);
|
|
285
|
+
|
|
286
|
+
if (!isValid) {
|
|
287
|
+
throw data("Locale not supported", { status: 404 });
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
292
|
+
const content = getIntlayer("page", params.locale);
|
|
293
|
+
|
|
294
|
+
return [
|
|
295
|
+
{ title: content.title },
|
|
296
|
+
{ content: content.description, name: "description" },
|
|
297
|
+
];
|
|
298
|
+
};
|
|
299
|
+
|
|
247
300
|
export default function Page() {
|
|
248
301
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
249
302
|
|
|
@@ -262,11 +315,34 @@ export default function Page() {
|
|
|
262
315
|
#### Página Acerca de
|
|
263
316
|
|
|
264
317
|
```tsx fileName="app/routes/($locale).about.tsx"
|
|
318
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
265
319
|
import { useIntlayer } from "react-intlayer";
|
|
266
|
-
import {
|
|
320
|
+
import { data } from "react-router";
|
|
321
|
+
|
|
322
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
323
|
+
import { Navbar } from "~/components/navbar";
|
|
267
324
|
|
|
268
325
|
import type { Route } from "./+types/($locale).about";
|
|
269
326
|
|
|
327
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
328
|
+
const { locale } = params;
|
|
329
|
+
|
|
330
|
+
const { isValid } = validatePrefix(locale);
|
|
331
|
+
|
|
332
|
+
if (!isValid) {
|
|
333
|
+
throw data("Locale not supported", { status: 404 });
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
338
|
+
const content = getIntlayer("about", params.locale);
|
|
339
|
+
|
|
340
|
+
return [
|
|
341
|
+
{ title: content.title },
|
|
342
|
+
{ content: content.description, name: "description" },
|
|
343
|
+
];
|
|
344
|
+
};
|
|
345
|
+
|
|
270
346
|
export default function AboutPage() {
|
|
271
347
|
const { title, content, homeLink } = useIntlayer("about");
|
|
272
348
|
|
|
@@ -487,7 +563,7 @@ export const useI18nHTMLAttributes = () => {
|
|
|
487
563
|
};
|
|
488
564
|
```
|
|
489
565
|
|
|
490
|
-
Este hook ya se usa en el componente de layout (`
|
|
566
|
+
Este hook ya se usa en el componente de layout (`root.tsx`) mostrado en el Paso 5.
|
|
491
567
|
|
|
492
568
|
### Paso 10: Añadir middleware (Opcional)
|
|
493
569
|
|
|
@@ -553,15 +553,15 @@ Intlayer vous aide à garder les traductions JSON synchronisées, à tester les
|
|
|
553
553
|
Installez les dépendances intlayer :
|
|
554
554
|
|
|
555
555
|
```bash packageManager="npm"
|
|
556
|
-
npm install intlayer @intlayer/sync-json-plugin
|
|
556
|
+
npm install intlayer @intlayer/sync-json-plugin --save-dev
|
|
557
557
|
```
|
|
558
558
|
|
|
559
559
|
```bash packageManager="pnpm"
|
|
560
|
-
pnpm add intlayer @intlayer/sync-json-plugin
|
|
560
|
+
pnpm add intlayer @intlayer/sync-json-plugin --save-dev
|
|
561
561
|
```
|
|
562
562
|
|
|
563
563
|
```bash packageManager="yarn"
|
|
564
|
-
yarn add intlayer @intlayer/sync-json-plugin
|
|
564
|
+
yarn add intlayer @intlayer/sync-json-plugin --dev
|
|
565
565
|
```
|
|
566
566
|
|
|
567
567
|
```ts fileName="intlayer.config.ts"
|
|
@@ -391,15 +391,15 @@ export const config = {
|
|
|
391
391
|
Installer les dépendances d'intlayer :
|
|
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
|
Créer le fichier de configuration intlayer :
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-09-04
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-27
|
|
4
4
|
title: Comment traduire votre React Router v7 – guide i18n 2025
|
|
5
5
|
description: Apprenez à ajouter l'internationalisation (i18n) à votre application React Router v7 en utilisant Intlayer. Suivez ce guide complet pour rendre votre application multilingue avec un routage sensible à la locale.
|
|
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: Mise à jour du Layout et gestion des 404
|
|
23
26
|
- version: 6.1.5
|
|
24
27
|
date: 2025-10-03
|
|
25
28
|
changes: Documentation mise à jour
|
|
@@ -174,10 +177,8 @@ Configurez votre routage avec des routes sensibles à la locale :
|
|
|
174
177
|
import { layout, route, type RouteConfig } from "@react-router/dev/routes";
|
|
175
178
|
|
|
176
179
|
export default [
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
route("/:lang?/about", "routes/about/page.tsx"), // Page À propos localisée
|
|
180
|
-
]),
|
|
180
|
+
route("/:lang?", "routes/page.tsx"), // Page d'accueil localisée
|
|
181
|
+
route("/:lang?/about", "routes/about/page.tsx"), // Page À propos localisée
|
|
181
182
|
] satisfies RouteConfig;
|
|
182
183
|
```
|
|
183
184
|
|
|
@@ -187,19 +188,50 @@ Configurez votre mise en page racine et les mises en page spécifiques à la loc
|
|
|
187
188
|
|
|
188
189
|
#### Mise en page racine
|
|
189
190
|
|
|
190
|
-
```tsx fileName="app/
|
|
191
|
+
```tsx fileName="app/root.tsx"
|
|
192
|
+
import { getLocaleFromPath } from "intlayer";
|
|
191
193
|
import { IntlayerProvider } from "react-intlayer";
|
|
192
|
-
import {
|
|
194
|
+
import {
|
|
195
|
+
data,
|
|
196
|
+
Meta,
|
|
197
|
+
Scripts,
|
|
198
|
+
ScrollRestoration,
|
|
199
|
+
useLoaderData,
|
|
200
|
+
} from "react-router";
|
|
201
|
+
import type { Route } from "./+types/root";
|
|
193
202
|
|
|
194
|
-
|
|
203
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
195
204
|
|
|
196
|
-
export
|
|
197
|
-
const
|
|
205
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
206
|
+
const locale = getLocaleFromPath(request.url);
|
|
207
|
+
|
|
208
|
+
if (!locale) {
|
|
209
|
+
throw data("Language not supported", { status: 404 });
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return { locale };
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function Layout({
|
|
216
|
+
children,
|
|
217
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
218
|
+
const data = useLoaderData<typeof loader>();
|
|
219
|
+
const { locale } = data ?? {};
|
|
198
220
|
|
|
199
221
|
return (
|
|
200
|
-
<
|
|
201
|
-
<
|
|
202
|
-
|
|
222
|
+
<html lang={locale}>
|
|
223
|
+
<head>
|
|
224
|
+
<meta charSet="utf-8" />
|
|
225
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
226
|
+
<Meta />
|
|
227
|
+
<Links />
|
|
228
|
+
</head>
|
|
229
|
+
<body>
|
|
230
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
231
|
+
<ScrollRestoration />
|
|
232
|
+
<Scripts />
|
|
233
|
+
</body>
|
|
234
|
+
</html>
|
|
203
235
|
);
|
|
204
236
|
}
|
|
205
237
|
```
|
|
@@ -313,9 +345,34 @@ Accédez à vos dictionnaires de contenu dans toute votre application :
|
|
|
313
345
|
|
|
314
346
|
#### Page d'accueil localisée
|
|
315
347
|
|
|
316
|
-
```tsx fileName="app/routes/
|
|
348
|
+
```tsx fileName="app/routes/page.tsx"
|
|
349
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
317
350
|
import { useIntlayer } from "react-intlayer";
|
|
318
|
-
import {
|
|
351
|
+
import { data } from "react-router";
|
|
352
|
+
|
|
353
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
354
|
+
|
|
355
|
+
import { Navbar } from "~/components/navbar";
|
|
356
|
+
import type { Route } from "./+types/page";
|
|
357
|
+
|
|
358
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
359
|
+
const { locale } = params;
|
|
360
|
+
|
|
361
|
+
const { isValid } = validatePrefix(locale);
|
|
362
|
+
|
|
363
|
+
if (!isValid) {
|
|
364
|
+
throw data("Locale not supported", { status: 404 });
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
369
|
+
const content = getIntlayer("page", params.locale);
|
|
370
|
+
|
|
371
|
+
return [
|
|
372
|
+
{ title: content.title },
|
|
373
|
+
{ content: content.description, name: "description" },
|
|
374
|
+
];
|
|
375
|
+
};
|
|
319
376
|
|
|
320
377
|
export default function Page() {
|
|
321
378
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
@@ -31,6 +31,8 @@ history:
|
|
|
31
31
|
|
|
32
32
|
Ce guide montre comment intégrer **Intlayer** pour une internationalisation fluide dans les projets React Router v7 en utilisant un **routage basé sur le système de fichiers** (`@react-router/fs-routes`) avec un routage sensible à la locale, la prise en charge de TypeScript, et des pratiques de développement modernes.
|
|
33
33
|
|
|
34
|
+
Pour le routage côté client, consultez le guide [Intlayer avec React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/fr/intlayer_with_react_router_v7.md).
|
|
35
|
+
|
|
34
36
|
## Table of Contents
|
|
35
37
|
|
|
36
38
|
<TOC/>
|
|
@@ -198,12 +200,13 @@ Créez les fichiers suivants dans votre répertoire `app/routes/` :
|
|
|
198
200
|
#### Structure des fichiers
|
|
199
201
|
|
|
200
202
|
```bash
|
|
201
|
-
app/
|
|
202
|
-
├──
|
|
203
|
-
|
|
204
|
-
├── ($locale)._index.
|
|
205
|
-
├── ($locale).
|
|
206
|
-
|
|
203
|
+
app/
|
|
204
|
+
├── root.tsx # Wrapper de mise en page pour les routes de locale
|
|
205
|
+
└──routes/
|
|
206
|
+
├── ($locale)._index.tsx # Page d'accueil (/, /es, etc.)
|
|
207
|
+
├── ($locale)._index.content.ts # Contenu de la page d'accueil
|
|
208
|
+
├── ($locale).about.tsx # Page À propos (/about, /es/about, etc.)
|
|
209
|
+
└── ($locale).about.content.ts # Contenu de la page À propos
|
|
207
210
|
```
|
|
208
211
|
|
|
209
212
|
Les conventions de nommage :
|
|
@@ -215,23 +218,50 @@ Les conventions de nommage :
|
|
|
215
218
|
|
|
216
219
|
#### Composant de mise en page
|
|
217
220
|
|
|
218
|
-
```tsx fileName="app/
|
|
221
|
+
```tsx fileName="app/root.tsx"
|
|
222
|
+
import { getLocaleFromPath } from "intlayer";
|
|
219
223
|
import { IntlayerProvider } from "react-intlayer";
|
|
220
|
-
import {
|
|
224
|
+
import {
|
|
225
|
+
isRouteErrorResponse,
|
|
226
|
+
Meta,
|
|
227
|
+
Outlet,
|
|
228
|
+
Scripts,
|
|
229
|
+
ScrollRestoration,
|
|
230
|
+
useLoaderData,
|
|
231
|
+
} from "react-router";
|
|
221
232
|
|
|
222
|
-
import {
|
|
233
|
+
import type { Route } from "./+types/root";
|
|
223
234
|
|
|
224
|
-
import
|
|
235
|
+
import "./app.css";
|
|
225
236
|
|
|
226
|
-
|
|
227
|
-
useI18nHTMLAttributes();
|
|
237
|
+
// links and ErrorBoundary code
|
|
228
238
|
|
|
229
|
-
|
|
239
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
240
|
+
const locale = getLocaleFromPath(request.url);
|
|
241
|
+
|
|
242
|
+
return { locale };
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
export function Layout({
|
|
246
|
+
children,
|
|
247
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
248
|
+
const data = useLoaderData<typeof loader>();
|
|
249
|
+
const { locale } = data ?? {};
|
|
230
250
|
|
|
231
251
|
return (
|
|
232
|
-
<
|
|
233
|
-
<
|
|
234
|
-
|
|
252
|
+
<html lang={locale}>
|
|
253
|
+
<head>
|
|
254
|
+
<meta charSet="utf-8" />
|
|
255
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
256
|
+
<Meta />
|
|
257
|
+
<Links />
|
|
258
|
+
</head>
|
|
259
|
+
<body>
|
|
260
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
261
|
+
<ScrollRestoration />
|
|
262
|
+
<Scripts />
|
|
263
|
+
</body>
|
|
264
|
+
</html>
|
|
235
265
|
);
|
|
236
266
|
}
|
|
237
267
|
```
|
|
@@ -239,11 +269,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
|
|
|
239
269
|
#### Page d'index
|
|
240
270
|
|
|
241
271
|
```tsx fileName="app/routes/($locale)._index.tsx"
|
|
272
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
242
273
|
import { useIntlayer } from "react-intlayer";
|
|
243
|
-
import {
|
|
274
|
+
import { data } from "react-router";
|
|
275
|
+
|
|
276
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
277
|
+
import { Navbar } from "~/components/navbar";
|
|
244
278
|
|
|
245
279
|
import type { Route } from "./+types/($locale)._index";
|
|
246
280
|
|
|
281
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
282
|
+
const { locale } = params;
|
|
283
|
+
|
|
284
|
+
const { isValid } = validatePrefix(locale);
|
|
285
|
+
|
|
286
|
+
if (!isValid) {
|
|
287
|
+
throw data("Locale not supported", { status: 404 });
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
292
|
+
const content = getIntlayer("page", params.locale);
|
|
293
|
+
|
|
294
|
+
return [
|
|
295
|
+
{ title: content.title },
|
|
296
|
+
{ content: content.description, name: "description" },
|
|
297
|
+
];
|
|
298
|
+
};
|
|
299
|
+
|
|
247
300
|
export default function Page() {
|
|
248
301
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
249
302
|
|
|
@@ -262,11 +315,34 @@ export default function Page() {
|
|
|
262
315
|
#### Page À propos
|
|
263
316
|
|
|
264
317
|
```tsx fileName="app/routes/($locale).about.tsx"
|
|
318
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
265
319
|
import { useIntlayer } from "react-intlayer";
|
|
266
|
-
import {
|
|
320
|
+
import { data } from "react-router";
|
|
321
|
+
|
|
322
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
323
|
+
import { Navbar } from "~/components/navbar";
|
|
267
324
|
|
|
268
325
|
import type { Route } from "./+types/($locale).about";
|
|
269
326
|
|
|
327
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
328
|
+
const { locale } = params;
|
|
329
|
+
|
|
330
|
+
const { isValid } = validatePrefix(locale);
|
|
331
|
+
|
|
332
|
+
if (!isValid) {
|
|
333
|
+
throw data("Locale not supported", { status: 404 });
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
338
|
+
const content = getIntlayer("about", params.locale);
|
|
339
|
+
|
|
340
|
+
return [
|
|
341
|
+
{ title: content.title },
|
|
342
|
+
{ content: content.description, name: "description" },
|
|
343
|
+
];
|
|
344
|
+
};
|
|
345
|
+
|
|
270
346
|
export default function AboutPage() {
|
|
271
347
|
const { title, content, homeLink } = useIntlayer("about");
|
|
272
348
|
|
|
@@ -487,7 +563,7 @@ export const useI18nHTMLAttributes = () => {
|
|
|
487
563
|
};
|
|
488
564
|
```
|
|
489
565
|
|
|
490
|
-
Ce hook est déjà utilisé dans le composant de mise en page (`
|
|
566
|
+
Ce hook est déjà utilisé dans le composant de mise en page (`root.tsx`) montré à l'Étape 5.
|
|
491
567
|
|
|
492
568
|
### Étape 10 : Ajouter un middleware (Optionnel)
|
|
493
569
|
|
|
@@ -553,15 +553,15 @@ Intlayer आपकी JSON अनुवादों को सिंक मे
|
|
|
553
553
|
Intlayer dependencies इंस्टॉल करें:
|
|
554
554
|
|
|
555
555
|
```bash packageManager="npm"
|
|
556
|
-
npm install intlayer @intlayer/sync-json-plugin
|
|
556
|
+
npm install intlayer @intlayer/sync-json-plugin --save-dev
|
|
557
557
|
```
|
|
558
558
|
|
|
559
559
|
```bash packageManager="pnpm"
|
|
560
|
-
pnpm add intlayer @intlayer/sync-json-plugin
|
|
560
|
+
pnpm add intlayer @intlayer/sync-json-plugin --save-dev
|
|
561
561
|
```
|
|
562
562
|
|
|
563
563
|
```bash packageManager="yarn"
|
|
564
|
-
yarn add intlayer @intlayer/sync-json-plugin
|
|
564
|
+
yarn add intlayer @intlayer/sync-json-plugin --dev
|
|
565
565
|
```
|
|
566
566
|
|
|
567
567
|
```ts fileName="intlayer.config.ts"
|
|
@@ -391,15 +391,15 @@ export const config = {
|
|
|
391
391
|
intlayer डिपेंडेंसीज़ इंस्टॉल करें:
|
|
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
|
intlayer कॉन्फ़िगरेशन फ़ाइल बनाएं:
|
|
@@ -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: जानें कि कैसे Intlayer का उपयोग करके अपने React Router v7 एप्लिकेशन में अंतरराष्ट्रीयकरण (i18n) जोड़ें। इस व्यापक गाइड का पालन करें ताकि आपका ऐप बहुभाषी और locale-aware रूटिंग के साथ हो।
|
|
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: दस्तावेज़ अपडेट किया गया
|
|
@@ -169,14 +172,11 @@ export default defineConfig({
|
|
|
169
172
|
अपने रूटिंग कॉन्फ़िगरेशन को स्थानीय-जानकारी वाले रूट्स के साथ सेट करें:
|
|
170
173
|
|
|
171
174
|
```typescript fileName="app/routes.ts"
|
|
172
|
-
typescript;
|
|
173
175
|
import { layout, route, type RouteConfig } from "@react-router/dev/routes";
|
|
174
176
|
|
|
175
177
|
export default [
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
route("/:lang?/about", "routes/about/page.tsx"), // स्थानीयकृत अबाउट पेज
|
|
179
|
-
]),
|
|
178
|
+
route("/:lang?", "routes/page.tsx"), // स्थानीयकृत होम पेज
|
|
179
|
+
route("/:lang?/about", "routes/about/page.tsx"), // स्थानीयकृत अबाउट पेज
|
|
180
180
|
] satisfies RouteConfig;
|
|
181
181
|
```
|
|
182
182
|
|
|
@@ -186,19 +186,50 @@ export default [
|
|
|
186
186
|
|
|
187
187
|
#### रूट लेआउट
|
|
188
188
|
|
|
189
|
-
```tsx fileName="app/
|
|
189
|
+
```tsx fileName="app/root.tsx"
|
|
190
|
+
import { getLocaleFromPath } from "intlayer";
|
|
190
191
|
import { IntlayerProvider } from "react-intlayer";
|
|
191
|
-
import {
|
|
192
|
+
import {
|
|
193
|
+
data,
|
|
194
|
+
Meta,
|
|
195
|
+
Scripts,
|
|
196
|
+
ScrollRestoration,
|
|
197
|
+
useLoaderData,
|
|
198
|
+
} from "react-router";
|
|
199
|
+
import type { Route } from "./+types/root";
|
|
192
200
|
|
|
193
|
-
|
|
201
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
194
202
|
|
|
195
|
-
export
|
|
196
|
-
const
|
|
203
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
204
|
+
const locale = getLocaleFromPath(request.url);
|
|
205
|
+
|
|
206
|
+
if (!locale) {
|
|
207
|
+
throw data("Language not supported", { status: 404 });
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return { locale };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function Layout({
|
|
214
|
+
children,
|
|
215
|
+
}: { children: React.ReactNode } & Route.ComponentProps) {
|
|
216
|
+
const data = useLoaderData<typeof loader>();
|
|
217
|
+
const { locale } = data ?? {};
|
|
197
218
|
|
|
198
219
|
return (
|
|
199
|
-
<
|
|
200
|
-
<
|
|
201
|
-
|
|
220
|
+
<html lang={locale}>
|
|
221
|
+
<head>
|
|
222
|
+
<meta charSet="utf-8" />
|
|
223
|
+
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
224
|
+
<Meta />
|
|
225
|
+
<Links />
|
|
226
|
+
</head>
|
|
227
|
+
<body>
|
|
228
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
229
|
+
<ScrollRestoration />
|
|
230
|
+
<Scripts />
|
|
231
|
+
</body>
|
|
232
|
+
</html>
|
|
202
233
|
);
|
|
203
234
|
}
|
|
204
235
|
```
|
|
@@ -313,9 +344,34 @@ export const useLocalizedNavigate = () => {
|
|
|
313
344
|
|
|
314
345
|
#### स्थानीयकृत होम पेज
|
|
315
346
|
|
|
316
|
-
```tsx fileName="app/routes/
|
|
347
|
+
```tsx fileName="app/routes/page.tsx"
|
|
348
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
317
349
|
import { useIntlayer } from "react-intlayer";
|
|
318
|
-
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
|
+
};
|
|
319
375
|
|
|
320
376
|
export default function Page() {
|
|
321
377
|
const { title, description, aboutLink } = useIntlayer("page");
|