@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
@@ -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/routes/
202
- ├── ($locale)._layout.tsx # Wrapper de layout para rutas de locale
203
- ├── ($locale)._index.tsx # Página de inicio (/:locale?)
204
- ├── ($locale)._index.content.ts # Contenido de la página de inicio
205
- ├── ($locale).about.tsx # Página Acerca de (/:locale?/about)
206
- └── ($locale).about.content.ts # Contenido de la página Acerca de
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/routes/($locale)._layout.tsx"
221
+ ```tsx fileName="app/root.tsx"
222
+ import { getLocaleFromPath } from "intlayer";
219
223
  import { IntlayerProvider } from "react-intlayer";
220
- import { Outlet } from "react-router";
224
+ import {
225
+ isRouteErrorResponse,
226
+ Meta,
227
+ Outlet,
228
+ Scripts,
229
+ ScrollRestoration,
230
+ useLoaderData,
231
+ } from "react-router";
221
232
 
222
- import { useI18nHTMLAttributes } from "~/hooks/useI18nHTMLAttributes";
233
+ import type { Route } from "./+types/root";
223
234
 
224
- import type { Route } from "./+types/($locale)._layout";
235
+ import "./app.css";
225
236
 
226
- export default function RootLayout({ params }: Route.ComponentProps) {
227
- useI18nHTMLAttributes();
237
+ // ... Unchanged App, links and ErrorBoundary code
228
238
 
229
- 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 ?? {};
230
250
 
231
251
  return (
232
- <IntlayerProvider locale={locale}>
233
- <Outlet />
234
- </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>
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 { 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";
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 { 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";
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 (`($locale)._layout.tsx`) mostrado en el Paso 5.
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 -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
  Installer les dépendances d'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
  Créer le fichier de configuration 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: 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
- layout("routes/layout.tsx", [
178
- route("/:lang?", "routes/page.tsx"), // Page d'accueil localisée
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/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 @@ 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/[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");
@@ -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/routes/
202
- ├── ($locale)._layout.tsx # Wrapper de mise en page pour les routes de locale
203
- ├── ($locale)._index.tsx # Page d'accueil (/:locale?)
204
- ├── ($locale)._index.content.ts # Contenu de la page d'accueil
205
- ├── ($locale).about.tsx # Page À propos (/:locale?/about)
206
- └── ($locale).about.content.ts # Contenu de la page À propos
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/routes/($locale)._layout.tsx"
221
+ ```tsx fileName="app/root.tsx"
222
+ import { getLocaleFromPath } from "intlayer";
219
223
  import { IntlayerProvider } from "react-intlayer";
220
- import { Outlet } from "react-router";
224
+ import {
225
+ isRouteErrorResponse,
226
+ Meta,
227
+ Outlet,
228
+ Scripts,
229
+ ScrollRestoration,
230
+ useLoaderData,
231
+ } from "react-router";
221
232
 
222
- import { useI18nHTMLAttributes } from "~/hooks/useI18nHTMLAttributes";
233
+ import type { Route } from "./+types/root";
223
234
 
224
- import type { Route } from "./+types/($locale)._layout";
235
+ import "./app.css";
225
236
 
226
- export default function RootLayout({ params }: Route.ComponentProps) {
227
- useI18nHTMLAttributes();
237
+ // links and ErrorBoundary code
228
238
 
229
- 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 ?? {};
230
250
 
231
251
  return (
232
- <IntlayerProvider locale={locale}>
233
- <Outlet />
234
- </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>
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 { 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";
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 { 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";
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 (`($locale)._layout.tsx`) montré à l'Étape 5.
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 -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
  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
  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: अपना 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
- layout("routes/layout.tsx", [
177
- route("/:lang?", "routes/page.tsx"), // स्थानीयकृत होम पेज
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/routes/layout.tsx"
189
+ ```tsx fileName="app/root.tsx"
190
+ import { getLocaleFromPath } from "intlayer";
190
191
  import { IntlayerProvider } from "react-intlayer";
191
- import { Outlet } from "react-router";
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
- import type { Route } from "./+types/layout";
201
+ // ... Unchanged App, links and ErrorBoundary code
194
202
 
195
- export default function RootLayout({ params }: Route.ComponentProps) {
196
- const { locale } = params;
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
- <IntlayerProvider locale={locale}>
200
- <Outlet />
201
- </IntlayerProvider>
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/[lang]/page.tsx"
347
+ ```tsx fileName="app/routes/page.tsx"
348
+ import { getIntlayer, validatePrefix } from "intlayer";
317
349
  import { useIntlayer } from "react-intlayer";
318
- import { LocalizedLink } from "~/components/localized-link";
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");