@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.
Files changed (173) hide show
  1. package/blog/ar/intlayer_with_i18next.md +4 -4
  2. package/blog/ar/intlayer_with_next-i18next.md +4 -4
  3. package/blog/ar/intlayer_with_next-intl.md +4 -4
  4. package/blog/ar/intlayer_with_react-i18next.md +4 -4
  5. package/blog/ar/intlayer_with_react-intl.md +4 -4
  6. package/blog/ar/intlayer_with_vue-i18n.md +4 -4
  7. package/blog/de/intlayer_with_i18next.md +4 -4
  8. package/blog/de/intlayer_with_next-i18next.md +4 -4
  9. package/blog/de/intlayer_with_next-intl.md +4 -4
  10. package/blog/de/intlayer_with_react-i18next.md +4 -4
  11. package/blog/de/intlayer_with_react-intl.md +4 -4
  12. package/blog/de/intlayer_with_vue-i18n.md +4 -4
  13. package/blog/en/intlayer_with_i18next.md +4 -4
  14. package/blog/en/intlayer_with_next-i18next.md +4 -4
  15. package/blog/en/intlayer_with_next-intl.md +4 -4
  16. package/blog/en/intlayer_with_react-i18next.md +4 -4
  17. package/blog/en/intlayer_with_react-intl.md +4 -4
  18. package/blog/en/intlayer_with_vue-i18n.md +4 -4
  19. package/blog/en-GB/intlayer_with_i18next.md +4 -4
  20. package/blog/en-GB/intlayer_with_next-i18next.md +4 -4
  21. package/blog/en-GB/intlayer_with_next-intl.md +4 -4
  22. package/blog/en-GB/intlayer_with_react-i18next.md +4 -4
  23. package/blog/en-GB/intlayer_with_react-intl.md +4 -4
  24. package/blog/en-GB/intlayer_with_vue-i18n.md +4 -4
  25. package/blog/es/intlayer_with_i18next.md +4 -4
  26. package/blog/es/intlayer_with_next-i18next.md +4 -4
  27. package/blog/es/intlayer_with_next-intl.md +4 -4
  28. package/blog/es/intlayer_with_react-i18next.md +4 -4
  29. package/blog/es/intlayer_with_react-intl.md +4 -4
  30. package/blog/es/intlayer_with_vue-i18n.md +4 -4
  31. package/blog/fr/intlayer_with_i18next.md +4 -4
  32. package/blog/fr/intlayer_with_next-i18next.md +4 -4
  33. package/blog/fr/intlayer_with_next-intl.md +4 -4
  34. package/blog/fr/intlayer_with_react-i18next.md +4 -4
  35. package/blog/fr/intlayer_with_react-intl.md +4 -4
  36. package/blog/fr/intlayer_with_vue-i18n.md +4 -4
  37. package/blog/hi/intlayer_with_i18next.md +4 -4
  38. package/blog/hi/intlayer_with_next-i18next.md +4 -4
  39. package/blog/hi/intlayer_with_next-intl.md +4 -4
  40. package/blog/hi/intlayer_with_react-i18next.md +4 -4
  41. package/blog/hi/intlayer_with_react-intl.md +4 -4
  42. package/blog/hi/intlayer_with_vue-i18n.md +4 -4
  43. package/blog/id/intlayer_with_i18next.md +4 -4
  44. package/blog/id/intlayer_with_next-i18next.md +4 -4
  45. package/blog/id/intlayer_with_next-intl.md +4 -4
  46. package/blog/id/intlayer_with_react-i18next.md +4 -4
  47. package/blog/id/intlayer_with_react-intl.md +4 -4
  48. package/blog/id/intlayer_with_vue-i18n.md +4 -4
  49. package/blog/it/intlayer_with_i18next.md +4 -4
  50. package/blog/it/intlayer_with_next-i18next.md +4 -4
  51. package/blog/it/intlayer_with_next-intl.md +4 -4
  52. package/blog/it/intlayer_with_react-i18next.md +4 -4
  53. package/blog/it/intlayer_with_react-intl.md +4 -4
  54. package/blog/it/intlayer_with_vue-i18n.md +4 -4
  55. package/blog/ja/intlayer_with_i18next.md +4 -4
  56. package/blog/ja/intlayer_with_next-i18next.md +4 -4
  57. package/blog/ja/intlayer_with_next-intl.md +4 -4
  58. package/blog/ja/intlayer_with_react-i18next.md +4 -4
  59. package/blog/ja/intlayer_with_react-intl.md +4 -4
  60. package/blog/ja/intlayer_with_vue-i18n.md +4 -4
  61. package/blog/ko/intlayer_with_i18next.md +4 -4
  62. package/blog/ko/intlayer_with_next-i18next.md +4 -4
  63. package/blog/ko/intlayer_with_next-intl.md +4 -4
  64. package/blog/ko/intlayer_with_react-i18next.md +4 -4
  65. package/blog/ko/intlayer_with_react-intl.md +4 -4
  66. package/blog/ko/intlayer_with_vue-i18n.md +4 -4
  67. package/blog/pl/intlayer_with_i18next.md +4 -4
  68. package/blog/pl/intlayer_with_next-i18next.md +4 -4
  69. package/blog/pl/intlayer_with_next-intl.md +4 -4
  70. package/blog/pl/intlayer_with_react-i18next.md +4 -4
  71. package/blog/pl/intlayer_with_react-intl.md +4 -4
  72. package/blog/pl/intlayer_with_vue-i18n.md +4 -4
  73. package/blog/pt/intlayer_with_i18next.md +4 -4
  74. package/blog/pt/intlayer_with_next-i18next.md +4 -4
  75. package/blog/pt/intlayer_with_next-intl.md +4 -4
  76. package/blog/pt/intlayer_with_react-i18next.md +4 -4
  77. package/blog/pt/intlayer_with_react-intl.md +4 -4
  78. package/blog/pt/intlayer_with_vue-i18n.md +4 -4
  79. package/blog/ru/intlayer_with_i18next.md +4 -4
  80. package/blog/ru/intlayer_with_next-i18next.md +4 -4
  81. package/blog/ru/intlayer_with_next-intl.md +4 -4
  82. package/blog/ru/intlayer_with_react-i18next.md +4 -4
  83. package/blog/ru/intlayer_with_react-intl.md +4 -4
  84. package/blog/ru/intlayer_with_vue-i18n.md +4 -4
  85. package/blog/tr/intlayer_with_i18next.md +4 -4
  86. package/blog/tr/intlayer_with_next-i18next.md +4 -4
  87. package/blog/tr/intlayer_with_next-intl.md +4 -4
  88. package/blog/tr/intlayer_with_react-i18next.md +4 -4
  89. package/blog/tr/intlayer_with_react-intl.md +4 -4
  90. package/blog/tr/intlayer_with_vue-i18n.md +4 -4
  91. package/blog/vi/intlayer_with_i18next.md +4 -4
  92. package/blog/vi/intlayer_with_next-i18next.md +4 -4
  93. package/blog/vi/intlayer_with_next-intl.md +4 -4
  94. package/blog/vi/intlayer_with_react-i18next.md +4 -4
  95. package/blog/vi/intlayer_with_react-intl.md +4 -4
  96. package/blog/vi/intlayer_with_vue-i18n.md +4 -4
  97. package/blog/zh/intlayer_with_i18next.md +4 -4
  98. package/blog/zh/intlayer_with_next-i18next.md +4 -4
  99. package/blog/zh/intlayer_with_next-intl.md +4 -4
  100. package/blog/zh/intlayer_with_react-i18next.md +4 -4
  101. package/blog/zh/intlayer_with_react-intl.md +4 -4
  102. package/blog/zh/intlayer_with_vue-i18n.md +4 -4
  103. package/docs/ar/intlayer_with_next-i18next.md +3 -3
  104. package/docs/ar/intlayer_with_next-intl.md +3 -3
  105. package/docs/ar/intlayer_with_react_router_v7.md +72 -16
  106. package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +2 -0
  107. package/docs/de/intlayer_with_next-i18next.md +3 -3
  108. package/docs/de/intlayer_with_next-intl.md +3 -3
  109. package/docs/de/intlayer_with_react_router_v7.md +72 -15
  110. package/docs/de/intlayer_with_react_router_v7_fs_routes.md +95 -19
  111. package/docs/en/configuration.md +1 -0
  112. package/docs/en/intlayer_with_next-i18next.md +3 -3
  113. package/docs/en/intlayer_with_next-intl.md +3 -3
  114. package/docs/en/intlayer_with_react_router_v7.md +74 -15
  115. package/docs/en/intlayer_with_react_router_v7_fs_routes.md +98 -19
  116. package/docs/en-GB/configuration.md +1 -0
  117. package/docs/en-GB/intlayer_with_next-i18next.md +3 -3
  118. package/docs/en-GB/intlayer_with_next-intl.md +3 -3
  119. package/docs/en-GB/intlayer_with_react_router_v7.md +73 -16
  120. package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +2 -0
  121. package/docs/es/intlayer_with_next-i18next.md +3 -3
  122. package/docs/es/intlayer_with_next-intl.md +3 -3
  123. package/docs/es/intlayer_with_react_router_v7.md +72 -15
  124. package/docs/es/intlayer_with_react_router_v7_fs_routes.md +95 -19
  125. package/docs/fr/intlayer_with_next-i18next.md +3 -3
  126. package/docs/fr/intlayer_with_next-intl.md +3 -3
  127. package/docs/fr/intlayer_with_react_router_v7.md +72 -15
  128. package/docs/fr/intlayer_with_react_router_v7_fs_routes.md +95 -19
  129. package/docs/hi/intlayer_with_next-i18next.md +3 -3
  130. package/docs/hi/intlayer_with_next-intl.md +3 -3
  131. package/docs/hi/intlayer_with_react_router_v7.md +72 -16
  132. package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +2 -0
  133. package/docs/id/intlayer_with_next-i18next.md +3 -3
  134. package/docs/id/intlayer_with_next-intl.md +3 -3
  135. package/docs/id/intlayer_with_react_router_v7.md +72 -15
  136. package/docs/id/intlayer_with_react_router_v7_fs_routes.md +2 -0
  137. package/docs/it/intlayer_with_next-i18next.md +3 -3
  138. package/docs/it/intlayer_with_next-intl.md +3 -3
  139. package/docs/it/intlayer_with_react_router_v7.md +72 -15
  140. package/docs/it/intlayer_with_react_router_v7_fs_routes.md +95 -19
  141. package/docs/ja/intlayer_with_next-i18next.md +3 -3
  142. package/docs/ja/intlayer_with_next-intl.md +3 -3
  143. package/docs/ja/intlayer_with_react_router_v7.md +72 -15
  144. package/docs/ja/intlayer_with_react_router_v7_fs_routes.md +95 -19
  145. package/docs/ko/intlayer_with_next-i18next.md +3 -3
  146. package/docs/ko/intlayer_with_next-intl.md +3 -3
  147. package/docs/ko/intlayer_with_react_router_v7.md +72 -15
  148. package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +2 -0
  149. package/docs/pl/intlayer_with_next-i18next.md +3 -3
  150. package/docs/pl/intlayer_with_next-intl.md +3 -3
  151. package/docs/pl/intlayer_with_react_router_v7.md +45 -13
  152. package/docs/pl/intlayer_with_react_router_v7_fs_routes.md +94 -18
  153. package/docs/pt/intlayer_with_next-i18next.md +3 -3
  154. package/docs/pt/intlayer_with_next-intl.md +3 -3
  155. package/docs/pt/intlayer_with_react_router_v7.md +79 -46
  156. package/docs/pt/intlayer_with_react_router_v7_fs_routes.md +95 -19
  157. package/docs/ru/intlayer_with_next-i18next.md +3 -3
  158. package/docs/ru/intlayer_with_next-intl.md +3 -3
  159. package/docs/ru/intlayer_with_react_router_v7.md +72 -15
  160. package/docs/ru/intlayer_with_react_router_v7_fs_routes.md +95 -19
  161. package/docs/tr/intlayer_with_next-i18next.md +3 -3
  162. package/docs/tr/intlayer_with_next-intl.md +3 -3
  163. package/docs/tr/intlayer_with_react_router_v7.md +72 -15
  164. package/docs/tr/intlayer_with_react_router_v7_fs_routes.md +95 -19
  165. package/docs/vi/intlayer_with_next-i18next.md +3 -3
  166. package/docs/vi/intlayer_with_next-intl.md +3 -3
  167. package/docs/vi/intlayer_with_react_router_v7.md +72 -15
  168. package/docs/vi/intlayer_with_react_router_v7_fs_routes.md +2 -0
  169. package/docs/zh/intlayer_with_next-i18next.md +3 -3
  170. package/docs/zh/intlayer_with_next-intl.md +3 -3
  171. package/docs/zh/intlayer_with_react_router_v7.md +72 -15
  172. package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +2 -0
  173. package/package.json +6 -6
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-12-07
3
- updatedAt: 2025-12-07
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/routes/
199
- ├── ($locale)._layout.tsx # Layout wrapper for locale routes
200
- ├── ($locale)._index.tsx # Home page (/:locale?)
201
- ├── ($locale)._index.content.ts # Home page content
202
- ├── ($locale).about.tsx # About page (/:locale?/about)
203
- └── ($locale).about.content.ts # About page content
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/routes/($locale)._layout.tsx"
221
+ ```tsx fileName="app/root.tsx"
222
+ import { getLocaleFromPath } from "intlayer";
216
223
  import { IntlayerProvider } from "react-intlayer";
217
- import { Outlet } from "react-router";
224
+ import {
225
+ isRouteErrorResponse,
226
+ Meta,
227
+ Outlet,
228
+ Scripts,
229
+ ScrollRestoration,
230
+ useLoaderData,
231
+ } from "react-router";
218
232
 
219
- import { useI18nHTMLAttributes } from "~/hooks/useI18nHTMLAttributes";
233
+ import type { Route } from "./+types/root";
220
234
 
221
- import type { Route } from "./+types/($locale)._layout";
235
+ import "./app.css";
222
236
 
223
- export default function RootLayout({ params }: Route.ComponentProps) {
224
- useI18nHTMLAttributes();
237
+ // ... Unchanged App, links and ErrorBoundary code
225
238
 
226
- const { locale } = params;
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
- <IntlayerProvider locale={locale}>
230
- <Outlet />
231
- </IntlayerProvider>
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 { LocalizedLink } from "~/components/localized-link";
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 { LocalizedLink } from "~/components/localized-link";
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
 
@@ -482,6 +482,7 @@ Intlayer supports multiple AI providers for enhanced flexibility and choice. Cur
482
482
  - **DeepSeek**
483
483
  - **Google Gemini**
484
484
  - **Meta Llama**
485
+ - **ollama**
485
486
 
486
487
  #### Properties
487
488
 
@@ -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 -D
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 -D
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 -D
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 -D
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 -D
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 -D
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-10-03
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
- layout("routes/layout.tsx", [
175
- route("/:lang?", "routes/page.tsx"), // Localised home page
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/routes/layout.tsx"
188
+ ```tsx fileName="app/root.tsx"
189
+ import { getLocaleFromPath } from "intlayer";
188
190
  import { IntlayerProvider } from "react-intlayer";
189
- import { Outlet } from "react-router";
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
- import type { Route } from "./+types/layout";
200
+ // ... Unchanged App, links and ErrorBoundary code
192
201
 
193
- export default function RootLayout({ params }: Route.ComponentProps) {
194
- const { locale } = params;
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
- <IntlayerProvider locale={locale}>
198
- <Outlet />
199
- </IntlayerProvider>
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/[lang]/page.tsx"
312
- import { useIntlayer } from "intlayer";
313
- import { LocalizedLink } from "~/components/localized-link";
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 -D
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 -D
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 -D
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 -D
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 -D
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 -D
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-10-03
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
- layout("routes/layout.tsx", [
178
- route("/:lang?", "routes/page.tsx"), // Página de inicio localizada
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/routes/layout.tsx"
191
+ ```tsx fileName="app/root.tsx"
192
+ import { getLocaleFromPath } from "intlayer";
191
193
  import { IntlayerProvider } from "react-intlayer";
192
- import { Outlet } from "react-router";
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
- import type { Route } from "./+types/layout";
203
+ // ... Unchanged App, links and ErrorBoundary code
195
204
 
196
- export default function RootLayout({ params }: Route.ComponentProps) {
197
- const { locale } = params;
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
- <IntlayerProvider locale={locale}>
201
- <Outlet />
202
- </IntlayerProvider>
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/[lang]/page.tsx"
348
+ ```tsx fileName="app/routes/page.tsx"
349
+ import { getIntlayer, validatePrefix } from "intlayer";
317
350
  import { useIntlayer } from "react-intlayer";
318
- import { LocalizedLink } from "~/components/localized-link";
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");