@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.
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 +8 -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
  Ten przewodnik pokazuje, jak zintegrować **Intlayer** dla płynnej internacjonalizacji w projektach React Router v7 używając **routingu opartego na systemie plików** (`@react-router/fs-routes`) z routingiem uwzględniającym lokalizację, wsparciem TypeScript oraz nowoczesnymi praktykami programistycznymi.
33
33
 
34
+ W przypadku routingu po stronie klienta, zapoznaj się z przewodnikiem [Intlayer z React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/intlayer_with_react_router_v7.md).
35
+
34
36
  ## Table of Contents
35
37
 
36
38
  <TOC/>
@@ -220,12 +222,13 @@ Utwórz następujące pliki w katalogu `app/routes/`:
220
222
  #### Struktura plików
221
223
 
222
224
  ```bash
223
- app/routes/
224
- ├── ($locale)._layout.tsx # Opakowanie layoutu dla tras lokalizacji
225
- ├── ($locale)._index.tsx # Strona główna (/:locale?)
226
- ├── ($locale)._index.content.ts # Zawartość strony głównej
227
- ├── ($locale).about.tsx # Strona O nas (/:locale?/about)
228
- └── ($locale).about.content.ts # Zawartość strony O nas
225
+ app/
226
+ ├── root.tsx # Opakowanie layoutu dla tras lokalizacji
227
+ └──routes/
228
+ ├── ($locale)._index.tsx # Strona główna (/, /es, itd.)
229
+ ├── ($locale)._index.content.ts # Zawartość strony głównej
230
+ ├── ($locale).about.tsx # Strona O nas (/about, /es/about, itd.)
231
+ └── ($locale).about.content.ts # Zawartość strony O nas
229
232
  ```
230
233
 
231
234
  Konwencje nazewnictwa:
@@ -237,23 +240,50 @@ Konwencje nazewnictwa:
237
240
 
238
241
  #### Komponent Layoutu
239
242
 
240
- ```tsx fileName="app/routes/($locale)._layout.tsx"
243
+ ```tsx fileName="app/root.tsx"
244
+ import { getLocaleFromPath } from "intlayer";
241
245
  import { IntlayerProvider } from "react-intlayer";
242
- import { Outlet } from "react-router";
246
+ import {
247
+ isRouteErrorResponse,
248
+ Meta,
249
+ Outlet,
250
+ Scripts,
251
+ ScrollRestoration,
252
+ useLoaderData,
253
+ } from "react-router";
243
254
 
244
- import { useI18nHTMLAttributes } from "~/hooks/useI18nHTMLAttributes";
255
+ import type { Route } from "./+types/root";
245
256
 
246
- import type { Route } from "./+types/($locale)._layout";
257
+ import "./app.css";
247
258
 
248
- export default function RootLayout({ params }: Route.ComponentProps) {
249
- useI18nHTMLAttributes();
259
+ // links and ErrorBoundary code
250
260
 
251
- const { locale } = params;
261
+ export async function loader({ request }: Route.LoaderArgs) {
262
+ const locale = getLocaleFromPath(request.url);
263
+
264
+ return { locale };
265
+ }
266
+
267
+ export function Layout({
268
+ children,
269
+ }: { children: React.ReactNode } & Route.ComponentProps) {
270
+ const data = useLoaderData<typeof loader>();
271
+ const { locale } = data ?? {};
252
272
 
253
273
  return (
254
- <IntlayerProvider locale={locale}>
255
- <Outlet />
256
- </IntlayerProvider>
274
+ <html lang={locale}>
275
+ <head>
276
+ <meta charSet="utf-8" />
277
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
278
+ <Meta />
279
+ <Links />
280
+ </head>
281
+ <body>
282
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
283
+ <ScrollRestoration />
284
+ <Scripts />
285
+ </body>
286
+ </html>
257
287
  );
258
288
  }
259
289
  ```
@@ -261,11 +291,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
261
291
  #### Strona indeksowa
262
292
 
263
293
  ```tsx fileName="app/routes/($locale)._index.tsx"
294
+ import { getIntlayer, validatePrefix } from "intlayer";
264
295
  import { useIntlayer } from "react-intlayer";
265
- import { LocalizedLink } from "~/components/localized-link";
296
+ import { data } from "react-router";
297
+
298
+ import { LocaleSwitcher } from "~/components/locale-switcher";
299
+ import { Navbar } from "~/components/navbar";
266
300
 
267
301
  import type { Route } from "./+types/($locale)._index";
268
302
 
303
+ export const loader = ({ params }: Route.LoaderArgs) => {
304
+ const { locale } = params;
305
+
306
+ const { isValid } = validatePrefix(locale);
307
+
308
+ if (!isValid) {
309
+ throw data("Locale not supported", { status: 404 });
310
+ }
311
+ };
312
+
313
+ export const meta: Route.MetaFunction = ({ params }) => {
314
+ const content = getIntlayer("page", params.locale);
315
+
316
+ return [
317
+ { title: content.title },
318
+ { content: content.description, name: "description" },
319
+ ];
320
+ };
321
+
269
322
  export default function Page() {
270
323
  const { title, description, aboutLink } = useIntlayer("page");
271
324
 
@@ -284,11 +337,34 @@ export default function Page() {
284
337
  #### Strona O nas
285
338
 
286
339
  ```tsx fileName="app/routes/($locale).about.tsx"
340
+ import { getIntlayer, validatePrefix } from "intlayer";
287
341
  import { useIntlayer } from "react-intlayer";
288
- import { LocalizedLink } from "~/components/localized-link";
342
+ import { data } from "react-router";
343
+
344
+ import { LocaleSwitcher } from "~/components/locale-switcher";
345
+ import { Navbar } from "~/components/navbar";
289
346
 
290
347
  import type { Route } from "./+types/($locale).about";
291
348
 
349
+ export const loader = ({ params }: Route.LoaderArgs) => {
350
+ const { locale } = params;
351
+
352
+ const { isValid } = validatePrefix(locale);
353
+
354
+ if (!isValid) {
355
+ throw data("Locale not supported", { status: 404 });
356
+ }
357
+ };
358
+
359
+ export const meta: Route.MetaFunction = ({ params }) => {
360
+ const content = getIntlayer("about", params.locale);
361
+
362
+ return [
363
+ { title: content.title },
364
+ { content: content.description, name: "description" },
365
+ ];
366
+ };
367
+
292
368
  export default function AboutPage() {
293
369
  const { title, content, homeLink } = useIntlayer("about");
294
370
 
@@ -552,15 +552,15 @@ O Intlayer ajuda você a manter as traduções JSON sincronizadas, testar chaves
552
552
  Instale as dependências do intlayer:
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
  Instale as dependências do 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
  Crie o arquivo de configuração do intlayer:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  createdAt: 2025-09-04
3
- updatedAt: 2025-09-04
3
+ updatedAt: 2025-12-27
4
4
  title: Como traduzir seu React Router v7 – guia i18n 2025
5
5
  description: Aprenda como adicionar internacionalização (i18n) à sua aplicação React Router v7 usando Intlayer. Siga este guia completo para tornar seu app multilíngue com roteamento sensível à localidade.
6
6
  keywords:
@@ -21,6 +21,9 @@ applicationTemplate: https://github.com/AydinTheFirst/react-router-intlayer
21
21
  author: AydinTheFirst
22
22
  youtubeVideo: https://www.youtube.com/watch?v=dS9L7uJeak4
23
23
  history:
24
+ - version: 7.5.6
25
+ date: 2025-12-27
26
+ changes: Atualizar Layout e lidar com 404
24
27
  - version: 5.8.2
25
28
  date: 2025-09-04
26
29
  changes: Adicionado para React Router v7
@@ -160,15 +163,12 @@ module.exports = config;
160
163
 
161
164
  Configure sua configuração de rotas com rotas que reconhecem o idioma:
162
165
 
163
- ```typescript fileName="app/routes.ts" codeFormat="typescript"
166
+ ```typescript fileName="app/routes.ts"
164
167
  import { layout, route, type RouteConfig } from "@react-router/dev/routes";
165
168
 
166
169
  export default [
167
- layout("routes/layout.tsx", [
168
- route("/", "routes/page.tsx"), // Página raiz - redireciona para o idioma
169
- route("/:lang", "routes/[lang]/page.tsx"), // Página inicial localizada
170
- route("/:lang?/about", "routes/[lang]/about/page.tsx"), // Página sobre localizada
171
- ]),
170
+ route("/:lang?", "routes/page.tsx"), // Página inicial localizada
171
+ route("/:lang?/about", "routes/about/page.tsx"), // Página sobre localizada
172
172
  ] satisfies RouteConfig;
173
173
  ```
174
174
 
@@ -195,17 +195,50 @@ Configure seu layout raiz e layouts específicos para cada localidade:
195
195
 
196
196
  #### Layout Raiz
197
197
 
198
- ```tsx fileName="app/routes/layout.tsx" codeFormat="typescript"
199
- tsx fileName="app/routes/layout.tsx" codeFormat="typescript"
200
- // app/routes/layout.tsx
201
- import { Outlet } from "react-router";
198
+ ```tsx fileName="app/root.tsx"
199
+ import { getLocaleFromPath } from "intlayer";
202
200
  import { IntlayerProvider } from "react-intlayer";
201
+ import {
202
+ data,
203
+ Meta,
204
+ Scripts,
205
+ ScrollRestoration,
206
+ useLoaderData,
207
+ } from "react-router";
208
+ import type { Route } from "./+types/root";
209
+
210
+ // ... Unchanged App, links and ErrorBoundary code
211
+
212
+ export async function loader({ request }: Route.LoaderArgs) {
213
+ const locale = getLocaleFromPath(request.url);
214
+
215
+ if (!locale) {
216
+ throw data("Language not supported", { status: 404 });
217
+ }
218
+
219
+ return { locale };
220
+ }
221
+
222
+ export function Layout({
223
+ children,
224
+ }: { children: React.ReactNode } & Route.ComponentProps) {
225
+ const data = useLoaderData<typeof loader>();
226
+ const { locale } = data ?? {};
203
227
 
204
- export default function RootLayout() {
205
228
  return (
206
- <IntlayerProvider>
207
- <Outlet />
208
- </IntlayerProvider>
229
+ <html lang={locale}>
230
+ <head>
231
+ <meta charSet="utf-8" />
232
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
233
+ <Meta />
234
+ <Links />
235
+ </head>
236
+ <body>
237
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
238
+ <ScrollRestoration />
239
+ <Scripts />
240
+ </body>
241
+ </html>
209
242
  );
210
243
  }
211
244
  ```
@@ -299,46 +332,46 @@ export default function LocalizedLink({ to, ...props }: RouterLinkProps) {
299
332
 
300
333
  Acesse seus dicionários de conteúdo em toda a sua aplicação:
301
334
 
302
- #### Página de Redirecionamento Raiz
335
+ #### Página Inicial Localizada
303
336
 
304
- ```tsx fileName="app/routes/page.tsx" codeFormat="typescript"
305
- import { useLocale } from "react-intlayer";
306
- import { Navigate } from "react-router";
337
+ ```tsx fileName="app/routes/page.tsx"
338
+ import { getIntlayer, validatePrefix } from "intlayer";
339
+ import { useIntlayer } from "react-intlayer";
340
+ import { data } from "react-router";
307
341
 
308
- export default function Page() {
309
- const { locale } = useLocale();
342
+ import { LocaleSwitcher } from "~/components/locale-switcher";
310
343
 
311
- return <Navigate replace to={locale} />;
312
- }
313
- ```
344
+ import { Navbar } from "~/components/navbar";
345
+ import type { Route } from "./+types/page";
314
346
 
315
- #### Página Inicial Localizada
347
+ export const loader = ({ params }: Route.LoaderArgs) => {
348
+ const { locale } = params;
316
349
 
317
- ```tsx fileName="app/routes/[lang]/page.tsx" codeFormat="typescript"
318
- import { useIntlayer } from "react-intlayer";
319
- import LocalizedLink from "~/components/localized-link";
350
+ const { isValid } = validatePrefix(locale);
351
+
352
+ if (!isValid) {
353
+ throw data("Locale not supported", { status: 404 });
354
+ }
355
+ };
356
+
357
+ export const meta: Route.MetaFunction = ({ params }) => {
358
+ const content = getIntlayer("page", params.locale);
359
+
360
+ return [
361
+ { title: content.title },
362
+ { content: content.description, name: "description" },
363
+ ];
364
+ };
320
365
 
321
366
  export default function Page() {
322
- const content = useIntlayer("page");
367
+ const { title, description, aboutLink } = useIntlayer("page");
323
368
 
324
369
  return (
325
- <div style={{ padding: "2rem", textAlign: "center" }}>
326
- <h1>{content.title}</h1>
327
- <p>{content.description}</p>
328
- <nav style={{ marginTop: "2rem" }}>
329
- <LocalizedLink
330
- to="/about"
331
- style={{
332
- display: "inline-block",
333
- padding: "0.5rem 1rem",
334
- backgroundColor: "#007bff",
335
- color: "white",
336
- textDecoration: "none",
337
- borderRadius: "4px",
338
- }}
339
- >
340
- {content.aboutLink}
341
- </LocalizedLink>
370
+ <div>
371
+ <h1>{title}</h1>
372
+ <p>{description}</p>
373
+ <nav>
374
+ <LocalizedLink to="/about">{aboutLink}</LocalizedLink>
342
375
  </nav>
343
376
  </div>
344
377
  );
@@ -31,6 +31,8 @@ history:
31
31
 
32
32
  Este guia demonstra como integrar o **Intlayer** para internacionalização perfeita em projetos React Router v7 usando **roteamento baseado em sistema de arquivos** (`@react-router/fs-routes`) com roteamento consciente de localidade, suporte a TypeScript e práticas modernas de desenvolvimento.
33
33
 
34
+ Para roteamento do lado do cliente, consulte o guia [Intlayer com React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/intlayer_with_react_router_v7.md).
35
+
34
36
  ## Índice
35
37
 
36
38
  <TOC/>
@@ -195,12 +197,13 @@ Crie os seguintes arquivos no seu diretório `app/routes/`:
195
197
  #### Estrutura de Arquivos
196
198
 
197
199
  ```bash
198
- app/routes/
199
- ├── ($locale)._layout.tsx # Wrapper de layout para rotas de locale
200
- ├── ($locale)._index.tsx # Página inicial (/:locale?)
201
- ├── ($locale)._index.content.ts # Conteúdo da página inicial
202
- ├── ($locale).about.tsx # Página About (/:locale?/about)
203
- └── ($locale).about.content.ts # Conteúdo da página About
200
+ app/
201
+ ├── root.tsx # Wrapper de layout para rotas de locale
202
+ └──routes/
203
+ ├── ($locale)._index.tsx # Página inicial (/, /es, etc.)
204
+ ├── ($locale)._index.content.ts # Conteúdo da página inicial
205
+ ├── ($locale).about.tsx # Página About (/about, /es/about, etc.)
206
+ └── ($locale).about.content.ts # Conteúdo da página About
204
207
  ```
205
208
 
206
209
  As convenções de nomenclatura:
@@ -212,23 +215,50 @@ As convenções de nomenclatura:
212
215
 
213
216
  #### Componente de Layout
214
217
 
215
- ```tsx fileName="app/routes/($locale)._layout.tsx"
218
+ ```tsx fileName="app/root.tsx"
219
+ import { getLocaleFromPath } from "intlayer";
216
220
  import { IntlayerProvider } from "react-intlayer";
217
- import { Outlet } from "react-router";
221
+ import {
222
+ isRouteErrorResponse,
223
+ Meta,
224
+ Outlet,
225
+ Scripts,
226
+ ScrollRestoration,
227
+ useLoaderData,
228
+ } from "react-router";
218
229
 
219
- import { useI18nHTMLAttributes } from "~/hooks/useI18nHTMLAttributes";
230
+ import type { Route } from "./+types/root";
220
231
 
221
- import type { Route } from "./+types/($locale)._layout";
232
+ import "./app.css";
222
233
 
223
- export default function RootLayout({ params }: Route.ComponentProps) {
224
- useI18nHTMLAttributes();
234
+ // links and ErrorBoundary code
225
235
 
226
- const { locale } = params;
236
+ export async function loader({ request }: Route.LoaderArgs) {
237
+ const locale = getLocaleFromPath(request.url);
238
+
239
+ return { locale };
240
+ }
241
+
242
+ export function Layout({
243
+ children,
244
+ }: { children: React.ReactNode } & Route.ComponentProps) {
245
+ const data = useLoaderData<typeof loader>();
246
+ const { locale } = data ?? {};
227
247
 
228
248
  return (
229
- <IntlayerProvider locale={locale}>
230
- <Outlet />
231
- </IntlayerProvider>
249
+ <html lang={locale}>
250
+ <head>
251
+ <meta charSet="utf-8" />
252
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
253
+ <Meta />
254
+ <Links />
255
+ </head>
256
+ <body>
257
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
258
+ <ScrollRestoration />
259
+ <Scripts />
260
+ </body>
261
+ </html>
232
262
  );
233
263
  }
234
264
  ```
@@ -236,11 +266,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
236
266
  #### Página Index
237
267
 
238
268
  ```tsx fileName="app/routes/($locale)._index.tsx"
269
+ import { getIntlayer, validatePrefix } from "intlayer";
239
270
  import { useIntlayer } from "react-intlayer";
240
- import { LocalizedLink } from "~/components/localized-link";
271
+ import { data } from "react-router";
272
+
273
+ import { LocaleSwitcher } from "~/components/locale-switcher";
274
+ import { Navbar } from "~/components/navbar";
241
275
 
242
276
  import type { Route } from "./+types/($locale)._index";
243
277
 
278
+ export const loader = ({ params }: Route.LoaderArgs) => {
279
+ const { locale } = params;
280
+
281
+ const { isValid } = validatePrefix(locale);
282
+
283
+ if (!isValid) {
284
+ throw data("Locale not supported", { status: 404 });
285
+ }
286
+ };
287
+
288
+ export const meta: Route.MetaFunction = ({ params }) => {
289
+ const content = getIntlayer("page", params.locale);
290
+
291
+ return [
292
+ { title: content.title },
293
+ { content: content.description, name: "description" },
294
+ ];
295
+ };
296
+
244
297
  export default function Page() {
245
298
  const { title, description, aboutLink } = useIntlayer("page");
246
299
 
@@ -259,11 +312,34 @@ export default function Page() {
259
312
  #### Página About
260
313
 
261
314
  ```tsx fileName="app/routes/($locale).about.tsx"
315
+ import { getIntlayer, validatePrefix } from "intlayer";
262
316
  import { useIntlayer } from "react-intlayer";
263
- import { LocalizedLink } from "~/components/localized-link";
317
+ import { data } from "react-router";
318
+
319
+ import { LocaleSwitcher } from "~/components/locale-switcher";
320
+ import { Navbar } from "~/components/navbar";
264
321
 
265
322
  import type { Route } from "./+types/($locale).about";
266
323
 
324
+ export const loader = ({ params }: Route.LoaderArgs) => {
325
+ const { locale } = params;
326
+
327
+ const { isValid } = validatePrefix(locale);
328
+
329
+ if (!isValid) {
330
+ throw data("Locale not supported", { status: 404 });
331
+ }
332
+ };
333
+
334
+ export const meta: Route.MetaFunction = ({ params }) => {
335
+ const content = getIntlayer("about", params.locale);
336
+
337
+ return [
338
+ { title: content.title },
339
+ { content: content.description, name: "description" },
340
+ ];
341
+ };
342
+
267
343
  export default function AboutPage() {
268
344
  const { title, content, homeLink } = useIntlayer("about");
269
345
 
@@ -482,7 +558,7 @@ export const useI18nHTMLAttributes = () => {
482
558
  };
483
559
  ```
484
560
 
485
- Este hook já é usado no componente de layout (`($locale)._layout.tsx`) mostrado no Passo 5.
561
+ Este hook já é usado no componente de layout (`root.tsx`) mostrado no Passo 5.
486
562
 
487
563
  ### Passo 10: Adicionar middleware (Opcional)
488
564
 
@@ -554,15 +554,15 @@ Intlayer помогает поддерживать JSON-переводы в си
554
554
  Установите зависимости intlayer:
555
555
 
556
556
  ```bash packageManager="npm"
557
- npm install intlayer @intlayer/sync-json-plugin -D
557
+ npm install intlayer @intlayer/sync-json-plugin --save-dev
558
558
  ```
559
559
 
560
560
  ```bash packageManager="pnpm"
561
- pnpm add intlayer @intlayer/sync-json-plugin -D
561
+ pnpm add intlayer @intlayer/sync-json-plugin --save-dev
562
562
  ```
563
563
 
564
564
  ```bash packageManager="yarn"
565
- yarn add intlayer @intlayer/sync-json-plugin -D
565
+ yarn add intlayer @intlayer/sync-json-plugin --dev
566
566
  ```
567
567
 
568
568
  ```ts fileName="intlayer.config.ts"
@@ -393,15 +393,15 @@ export const config = {
393
393
  Установите зависимости intlayer:
394
394
 
395
395
  ```bash packageManager="npm"
396
- npm install intlayer @intlayer/sync-json-plugin -D
396
+ npm install intlayer @intlayer/sync-json-plugin --save-dev
397
397
  ```
398
398
 
399
399
  ```bash packageManager="yarn"
400
- yarn add intlayer @intlayer/sync-json-plugin -D
400
+ yarn add intlayer @intlayer/sync-json-plugin --dev
401
401
  ```
402
402
 
403
403
  ```bash packageManager="pnpm"
404
- pnpm add intlayer @intlayer/sync-json-plugin -D
404
+ pnpm add intlayer @intlayer/sync-json-plugin --save-dev
405
405
  ```
406
406
 
407
407
  Создайте файл конфигурации intlayer: