@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-12-07
|
|
3
|
-
updatedAt: 2025-12-
|
|
3
|
+
updatedAt: 2025-12-27
|
|
4
4
|
title: How to translate your React Router v7 (File-System Routes) app – i18n guide 2025
|
|
5
5
|
description: Learn how to add internationalization (i18n) to your React Router v7 application using Intlayer with file-system based routing. Follow this comprehensive guide to make your app multilingual with locale-aware routing.
|
|
6
6
|
keywords:
|
|
@@ -22,6 +22,9 @@ slugs:
|
|
|
22
22
|
applicationTemplate: https://github.com/aymericzip/intlayer-react-router-v7-fs-routes-template
|
|
23
23
|
youtubeVideo: https://www.youtube.com/watch?v=dS9L7uJeak4
|
|
24
24
|
history:
|
|
25
|
+
- version: 7.5.6
|
|
26
|
+
date: 2025-12-27
|
|
27
|
+
changes: Update Layout and handle 404
|
|
25
28
|
- version: 7.3.4
|
|
26
29
|
date: 2025-12-08
|
|
27
30
|
changes: Init history
|
|
@@ -31,6 +34,8 @@ history:
|
|
|
31
34
|
|
|
32
35
|
This guide demonstrates how to integrate **Intlayer** for seamless internationalization in React Router v7 projects using **file-system based routing** (`@react-router/fs-routes`) with locale-aware routing, TypeScript support, and modern development practices.
|
|
33
36
|
|
|
37
|
+
For client-side routing, refer to the [Intlayer with React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/intlayer_with_react_router_v7.md) guide.
|
|
38
|
+
|
|
34
39
|
## Table of Contents
|
|
35
40
|
|
|
36
41
|
<TOC/>
|
|
@@ -195,12 +200,13 @@ Create the following files in your `app/routes/` directory:
|
|
|
195
200
|
#### File Structure
|
|
196
201
|
|
|
197
202
|
```bash
|
|
198
|
-
app/
|
|
199
|
-
├──
|
|
200
|
-
|
|
201
|
-
├── ($locale)._index.
|
|
202
|
-
├── ($locale).
|
|
203
|
-
|
|
203
|
+
app/
|
|
204
|
+
├── root.tsx # Layout wrapper for locale routes
|
|
205
|
+
└──routes/
|
|
206
|
+
├── ($locale)._index.tsx # Home page (/, /es, etc.)
|
|
207
|
+
├── ($locale)._index.content.ts # Home page content
|
|
208
|
+
├── ($locale).about.tsx # About page (/about, /es/about, etc.)
|
|
209
|
+
└── ($locale).about.content.ts # About page content
|
|
204
210
|
```
|
|
205
211
|
|
|
206
212
|
The naming conventions:
|
|
@@ -212,23 +218,50 @@ The naming conventions:
|
|
|
212
218
|
|
|
213
219
|
#### Layout Component
|
|
214
220
|
|
|
215
|
-
```tsx fileName="app/
|
|
221
|
+
```tsx fileName="app/root.tsx"
|
|
222
|
+
import { getLocaleFromPath } from "intlayer";
|
|
216
223
|
import { IntlayerProvider } from "react-intlayer";
|
|
217
|
-
import {
|
|
224
|
+
import {
|
|
225
|
+
isRouteErrorResponse,
|
|
226
|
+
Meta,
|
|
227
|
+
Outlet,
|
|
228
|
+
Scripts,
|
|
229
|
+
ScrollRestoration,
|
|
230
|
+
useLoaderData,
|
|
231
|
+
} from "react-router";
|
|
218
232
|
|
|
219
|
-
import {
|
|
233
|
+
import type { Route } from "./+types/root";
|
|
220
234
|
|
|
221
|
-
import
|
|
235
|
+
import "./app.css";
|
|
222
236
|
|
|
223
|
-
|
|
224
|
-
useI18nHTMLAttributes();
|
|
237
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
225
238
|
|
|
226
|
-
|
|
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 ?? {};
|
|
227
250
|
|
|
228
251
|
return (
|
|
229
|
-
<
|
|
230
|
-
<
|
|
231
|
-
|
|
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>
|
|
232
265
|
);
|
|
233
266
|
}
|
|
234
267
|
```
|
|
@@ -236,11 +269,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
|
|
|
236
269
|
#### Index Page
|
|
237
270
|
|
|
238
271
|
```tsx fileName="app/routes/($locale)._index.tsx"
|
|
272
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
239
273
|
import { useIntlayer } from "react-intlayer";
|
|
240
|
-
import {
|
|
274
|
+
import { data } from "react-router";
|
|
275
|
+
|
|
276
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
277
|
+
import { Navbar } from "~/components/navbar";
|
|
241
278
|
|
|
242
279
|
import type { Route } from "./+types/($locale)._index";
|
|
243
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
|
+
|
|
244
300
|
export default function Page() {
|
|
245
301
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
246
302
|
|
|
@@ -259,11 +315,34 @@ export default function Page() {
|
|
|
259
315
|
#### About Page
|
|
260
316
|
|
|
261
317
|
```tsx fileName="app/routes/($locale).about.tsx"
|
|
318
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
262
319
|
import { useIntlayer } from "react-intlayer";
|
|
263
|
-
import {
|
|
320
|
+
import { data } from "react-router";
|
|
321
|
+
|
|
322
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
323
|
+
import { Navbar } from "~/components/navbar";
|
|
264
324
|
|
|
265
325
|
import type { Route } from "./+types/($locale).about";
|
|
266
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
|
+
|
|
267
346
|
export default function AboutPage() {
|
|
268
347
|
const { title, content, homeLink } = useIntlayer("about");
|
|
269
348
|
|
|
@@ -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 internationalisation (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
|
|
@@ -171,10 +174,8 @@ Set up your routing configuration with locale-aware routes:
|
|
|
171
174
|
import { layout, route, type RouteConfig } from "@react-router/dev/routes";
|
|
172
175
|
|
|
173
176
|
export default [
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
route("/:lang?/about", "routes/about/page.tsx"), // Localised about page
|
|
177
|
-
]),
|
|
177
|
+
route("/:lang?", "routes/page.tsx"), // Localised home page
|
|
178
|
+
route("/:lang?/about", "routes/about/page.tsx"), // Localised about page
|
|
178
179
|
] satisfies RouteConfig;
|
|
179
180
|
```
|
|
180
181
|
|
|
@@ -184,19 +185,50 @@ Set up your root layout and locale-specific layouts:
|
|
|
184
185
|
|
|
185
186
|
#### Root Layout
|
|
186
187
|
|
|
187
|
-
```tsx fileName="app/
|
|
188
|
+
```tsx fileName="app/root.tsx"
|
|
189
|
+
import { getLocaleFromPath } from "intlayer";
|
|
188
190
|
import { IntlayerProvider } from "react-intlayer";
|
|
189
|
-
import {
|
|
191
|
+
import {
|
|
192
|
+
data,
|
|
193
|
+
Meta,
|
|
194
|
+
Scripts,
|
|
195
|
+
ScrollRestoration,
|
|
196
|
+
useLoaderData,
|
|
197
|
+
} from "react-router";
|
|
198
|
+
import type { Route } from "./+types/root";
|
|
190
199
|
|
|
191
|
-
|
|
200
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
192
201
|
|
|
193
|
-
export
|
|
194
|
-
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 ?? {};
|
|
195
217
|
|
|
196
218
|
return (
|
|
197
|
-
<
|
|
198
|
-
<
|
|
199
|
-
|
|
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>
|
|
200
232
|
);
|
|
201
233
|
}
|
|
202
234
|
```
|
|
@@ -308,9 +340,34 @@ Access your content dictionaries throughout your application:
|
|
|
308
340
|
|
|
309
341
|
#### Localised Home Page
|
|
310
342
|
|
|
311
|
-
```tsx fileName="app/routes/
|
|
312
|
-
import {
|
|
313
|
-
import {
|
|
343
|
+
```tsx fileName="app/routes/page.tsx"
|
|
344
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
345
|
+
import { useIntlayer } from "react-intlayer";
|
|
346
|
+
import { data } from "react-router";
|
|
347
|
+
|
|
348
|
+
import { LocaleSwitcher } from "~/components/locale-switcher";
|
|
349
|
+
|
|
350
|
+
import { Navbar } from "~/components/navbar";
|
|
351
|
+
import type { Route } from "./+types/page";
|
|
352
|
+
|
|
353
|
+
export const loader = ({ params }: Route.LoaderArgs) => {
|
|
354
|
+
const { locale } = params;
|
|
355
|
+
|
|
356
|
+
const { isValid } = validatePrefix(locale);
|
|
357
|
+
|
|
358
|
+
if (!isValid) {
|
|
359
|
+
throw data("Locale not supported", { status: 404 });
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
export const meta: Route.MetaFunction = ({ params }) => {
|
|
364
|
+
const content = getIntlayer("page", params.locale);
|
|
365
|
+
|
|
366
|
+
return [
|
|
367
|
+
{ title: content.title },
|
|
368
|
+
{ content: content.description, name: "description" },
|
|
369
|
+
];
|
|
370
|
+
};
|
|
314
371
|
|
|
315
372
|
export default function Page() {
|
|
316
373
|
const { title, description, aboutLink } = useIntlayer("page");
|
|
@@ -32,6 +32,8 @@ history:
|
|
|
32
32
|
|
|
33
33
|
This guide demonstrates how to integrate **Intlayer** for seamless internationalisation in React Router v7 projects with locale-aware routing, TypeScript support, and modern development practices.
|
|
34
34
|
|
|
35
|
+
For client-side routing, refer to the [Intlayer with React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en-GB/intlayer_with_react_router_v7.md) guide.
|
|
36
|
+
|
|
35
37
|
## Table of Contents
|
|
36
38
|
|
|
37
39
|
<TOC/>
|
|
@@ -553,15 +553,15 @@ Intlayer te ayuda a mantener las traducciones JSON sincronizadas, probar las cla
|
|
|
553
553
|
Instala las dependencias de 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
|
Instala las dependencias de 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
|
Crea el archivo de configuración de intlayer:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-09-04
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-12-27
|
|
4
4
|
title: Cómo traducir tu React Router v7 – guía i18n 2025
|
|
5
5
|
description: Aprende cómo agregar internacionalización (i18n) a tu aplicación React Router v7 usando Intlayer. Sigue esta guía completa para hacer tu aplicación multilingüe con enrutamiento consciente del 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: Actualizar Layout y manejar 404
|
|
23
26
|
- version: 6.1.5
|
|
24
27
|
date: 2025-10-03
|
|
25
28
|
changes: Documento actualizado
|
|
@@ -174,10 +177,8 @@ Configura tu enrutamiento con rutas conscientes del 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"), // Página "acerca de" localizada
|
|
180
|
-
]),
|
|
180
|
+
route("/:lang?", "routes/page.tsx"), // Página de inicio localizada
|
|
181
|
+
route("/:lang?/about", "routes/about/page.tsx"), // Página "acerca de" localizada
|
|
181
182
|
] satisfies RouteConfig;
|
|
182
183
|
```
|
|
183
184
|
|
|
@@ -187,19 +188,50 @@ Configura tu layout raíz y los layouts específicos por localización:
|
|
|
187
188
|
|
|
188
189
|
#### Layout Raíz
|
|
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 @@ Accede a tus diccionarios de contenido a lo largo de toda tu aplicación:
|
|
|
313
345
|
|
|
314
346
|
#### Página de inicio localizada
|
|
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");
|