@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-09-04
3
- updatedAt: 2025-10-03
3
+ updatedAt: 2025-12-27
4
4
  title: Как перевести ваше React Router v7 – руководство i18n 2025
5
5
  description: Узнайте, как добавить интернационализацию (i18n) в ваше приложение на React Router v7 с помощью Intlayer. Следуйте этому подробному руководству, чтобы сделать ваше приложение многоязычным с маршрутизацией, учитывающей локаль.
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: Обновить Layout и обработать 404
23
26
  - version: 6.1.5
24
27
  date: 2025-10-03
25
28
  changes: Обновлена документация
@@ -173,10 +176,8 @@ export default defineConfig({
173
176
  import { layout, route, type RouteConfig } from "@react-router/dev/routes";
174
177
 
175
178
  export default [
176
- layout("routes/layout.tsx", [
177
- route("/:lang?", "routes/page.tsx"), // Локализованная главная страница
178
- route("/:lang?/about", "routes/about/page.tsx"), // Локализованная страница "О нас"
179
- ]),
179
+ route("/:lang?", "routes/page.tsx"), // Локализованная главная страница
180
+ route("/:lang?/about", "routes/about/page.tsx"), // Локализованная страница "О нас"
180
181
  ] satisfies RouteConfig;
181
182
  ```
182
183
 
@@ -186,19 +187,50 @@ export default [
186
187
 
187
188
  #### Корневой Layout
188
189
 
189
- ```tsx fileName="app/routes/layout.tsx"
190
+ ```tsx fileName="app/root.tsx"
191
+ import { getLocaleFromPath } from "intlayer";
190
192
  import { IntlayerProvider } from "react-intlayer";
191
- import { Outlet } from "react-router";
193
+ import {
194
+ data,
195
+ Meta,
196
+ Scripts,
197
+ ScrollRestoration,
198
+ useLoaderData,
199
+ } from "react-router";
200
+ import type { Route } from "./+types/root";
192
201
 
193
- import type { Route } from "./+types/layout";
202
+ // ... Unchanged App, links and ErrorBoundary code
194
203
 
195
- export default function RootLayout({ params }: Route.ComponentProps) {
196
- const { locale } = params;
204
+ export async function loader({ request }: Route.LoaderArgs) {
205
+ const locale = getLocaleFromPath(request.url);
206
+
207
+ if (!locale) {
208
+ throw data("Language not supported", { status: 404 });
209
+ }
210
+
211
+ return { locale };
212
+ }
213
+
214
+ export function Layout({
215
+ children,
216
+ }: { children: React.ReactNode } & Route.ComponentProps) {
217
+ const data = useLoaderData<typeof loader>();
218
+ const { locale } = data ?? {};
197
219
 
198
220
  return (
199
- <IntlayerProvider locale={locale}>
200
- <Outlet />
201
- </IntlayerProvider>
221
+ <html lang={locale}>
222
+ <head>
223
+ <meta charSet="utf-8" />
224
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
225
+ <Meta />
226
+ <Links />
227
+ </head>
228
+ <body>
229
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
230
+ <ScrollRestoration />
231
+ <Scripts />
232
+ </body>
233
+ </html>
202
234
  );
203
235
  }
204
236
  ```
@@ -312,9 +344,34 @@ export const useLocalizedNavigate = () => {
312
344
 
313
345
  #### Локализованная главная страница
314
346
 
315
- ```tsx fileName="app/routes/[lang]/page.tsx"
347
+ ```tsx fileName="app/routes/page.tsx"
348
+ import { getIntlayer, validatePrefix } from "intlayer";
316
349
  import { useIntlayer } from "react-intlayer";
317
- 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
+ };
318
375
 
319
376
  export default function Page() {
320
377
  const { title, description, aboutLink } = useIntlayer("page");
@@ -31,6 +31,8 @@ history:
31
31
 
32
32
  Это руководство демонстрирует, как интегрировать **Intlayer** для бесшовной интернационализации в проектах на React Router v7 с использованием **маршрутизации на основе файловой системы** (`@react-router/fs-routes`) с маршрутизацией, учитывающей локаль, поддержкой TypeScript и современными практиками разработки.
33
33
 
34
+ Для клиентской маршрутизации обратитесь к руководству [Intlayer с React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/intlayer_with_react_router_v7.md).
35
+
34
36
  ## Table of Contents
35
37
 
36
38
  <TOC/>
@@ -197,12 +199,13 @@ export default routes;
197
199
  #### Структура файлов
198
200
 
199
201
  ```bash
200
- app/routes/
201
- ├── ($locale)._layout.tsx # Обертка layout для маршрутов локали
202
- ├── ($locale)._index.tsx # Главная страница (/:locale?)
203
- ├── ($locale)._index.content.ts # Контент главной страницы
204
- ├── ($locale).about.tsx # Страница нас" (/:locale?/about)
205
- └── ($locale).about.content.ts # Контент страницы "О нас"
202
+ app/
203
+ ├── root.tsx # Обертка layout для маршрутов локали
204
+ └──routes/
205
+ ├── ($locale)._index.tsx # Главная страница (/, /es, и т.д.)
206
+ ├── ($locale)._index.content.ts # Контент главной страницы
207
+ ├── ($locale).about.tsx # Страница "О нас" (/about, /es/about, и т.д.)
208
+ └── ($locale).about.content.ts # Контент страницы "О нас"
206
209
  ```
207
210
 
208
211
  Соглашения об именовании:
@@ -214,23 +217,50 @@ app/routes/
214
217
 
215
218
  #### Компонент Layout
216
219
 
217
- ```tsx fileName="app/routes/($locale)._layout.tsx"
220
+ ```tsx fileName="app/root.tsx"
221
+ import { getLocaleFromPath } from "intlayer";
218
222
  import { IntlayerProvider } from "react-intlayer";
219
- import { Outlet } from "react-router";
223
+ import {
224
+ isRouteErrorResponse,
225
+ Meta,
226
+ Outlet,
227
+ Scripts,
228
+ ScrollRestoration,
229
+ useLoaderData,
230
+ } from "react-router";
220
231
 
221
- import { useI18nHTMLAttributes } from "~/hooks/useI18nHTMLAttributes";
232
+ import type { Route } from "./+types/root";
222
233
 
223
- import type { Route } from "./+types/($locale)._layout";
234
+ import "./app.css";
224
235
 
225
- export default function RootLayout({ params }: Route.ComponentProps) {
226
- useI18nHTMLAttributes();
236
+ // links and ErrorBoundary code
227
237
 
228
- const { locale } = params;
238
+ export async function loader({ request }: Route.LoaderArgs) {
239
+ const locale = getLocaleFromPath(request.url);
240
+
241
+ return { locale };
242
+ }
243
+
244
+ export function Layout({
245
+ children,
246
+ }: { children: React.ReactNode } & Route.ComponentProps) {
247
+ const data = useLoaderData<typeof loader>();
248
+ const { locale } = data ?? {};
229
249
 
230
250
  return (
231
- <IntlayerProvider locale={locale}>
232
- <Outlet />
233
- </IntlayerProvider>
251
+ <html lang={locale}>
252
+ <head>
253
+ <meta charSet="utf-8" />
254
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
255
+ <Meta />
256
+ <Links />
257
+ </head>
258
+ <body>
259
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
260
+ <ScrollRestoration />
261
+ <Scripts />
262
+ </body>
263
+ </html>
234
264
  );
235
265
  }
236
266
  ```
@@ -238,11 +268,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
238
268
  #### Индексная страница
239
269
 
240
270
  ```tsx fileName="app/routes/($locale)._index.tsx"
271
+ import { getIntlayer, validatePrefix } from "intlayer";
241
272
  import { useIntlayer } from "react-intlayer";
242
- import { LocalizedLink } from "~/components/localized-link";
273
+ import { data } from "react-router";
274
+
275
+ import { LocaleSwitcher } from "~/components/locale-switcher";
276
+ import { Navbar } from "~/components/navbar";
243
277
 
244
278
  import type { Route } from "./+types/($locale)._index";
245
279
 
280
+ export const loader = ({ params }: Route.LoaderArgs) => {
281
+ const { locale } = params;
282
+
283
+ const { isValid } = validatePrefix(locale);
284
+
285
+ if (!isValid) {
286
+ throw data("Locale not supported", { status: 404 });
287
+ }
288
+ };
289
+
290
+ export const meta: Route.MetaFunction = ({ params }) => {
291
+ const content = getIntlayer("page", params.locale);
292
+
293
+ return [
294
+ { title: content.title },
295
+ { content: content.description, name: "description" },
296
+ ];
297
+ };
298
+
246
299
  export default function Page() {
247
300
  const { title, description, aboutLink } = useIntlayer("page");
248
301
 
@@ -261,11 +314,34 @@ export default function Page() {
261
314
  #### Страница "О нас"
262
315
 
263
316
  ```tsx fileName="app/routes/($locale).about.tsx"
317
+ import { getIntlayer, validatePrefix } from "intlayer";
264
318
  import { useIntlayer } from "react-intlayer";
265
- import { LocalizedLink } from "~/components/localized-link";
319
+ import { data } from "react-router";
320
+
321
+ import { LocaleSwitcher } from "~/components/locale-switcher";
322
+ import { Navbar } from "~/components/navbar";
266
323
 
267
324
  import type { Route } from "./+types/($locale).about";
268
325
 
326
+ export const loader = ({ params }: Route.LoaderArgs) => {
327
+ const { locale } = params;
328
+
329
+ const { isValid } = validatePrefix(locale);
330
+
331
+ if (!isValid) {
332
+ throw data("Locale not supported", { status: 404 });
333
+ }
334
+ };
335
+
336
+ export const meta: Route.MetaFunction = ({ params }) => {
337
+ const content = getIntlayer("about", params.locale);
338
+
339
+ return [
340
+ { title: content.title },
341
+ { content: content.description, name: "description" },
342
+ ];
343
+ };
344
+
269
345
  export default function AboutPage() {
270
346
  const { title, content, homeLink } = useIntlayer("about");
271
347
 
@@ -486,7 +562,7 @@ export const useI18nHTMLAttributes = () => {
486
562
  };
487
563
  ```
488
564
 
489
- Этот хук уже используется в компоненте layout (`($locale)._layout.tsx`), показанном в Шаге 5.
565
+ Этот хук уже используется в компоненте layout (`root.tsx`), показанном в Шаге 5.
490
566
 
491
567
  ### Шаг 10: Добавьте middleware (необязательно)
492
568
 
@@ -552,15 +552,15 @@ Intlayer, JSON çevirilerinizi senkronize tutmanıza, eksik anahtarları test et
552
552
  Intlayer bağımlılıklarını yükleyin:
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
  Intlayer bağımlılıklarını yükleyin:
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 yapılandırma dosyasını oluşturun:
@@ -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 uygulamanızı nasıl çevirirsiniz – i18n rehberi 2025
5
5
  description: React Router v7 uygulamanıza Intlayer kullanarak uluslararasılaştırmayı (i18n) nasıl ekleyeceğinizi öğrenin. Uygulamanızı yerel dil farkındalıklı yönlendirme ile çok dilli hale getirmek için bu kapsamlı rehberi takip edin.
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: Layout'u güncelle ve 404'ü yönet
23
26
  - version: 6.1.5
24
27
  date: 2025-10-03
25
28
  changes: Doküman güncellendi
@@ -171,10 +174,8 @@ Yerel dil farkındalığı olan rotalarla yönlendirme yapılandırmanızı ayar
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"), // Yerelleştirilmiş ana sayfa
176
- route("/:lang?/about", "routes/about/page.tsx"), // Yerelleştirilmiş hakkında sayfası
177
- ]),
177
+ route("/:lang?", "routes/page.tsx"), // Yerelleştirilmiş ana sayfa
178
+ route("/:lang?/about", "routes/about/page.tsx"), // Yerelleştirilmiş hakkında sayfası
178
179
  ] satisfies RouteConfig;
179
180
  ```
180
181
 
@@ -184,19 +185,50 @@ Kök layout ve dil bazlı layout'larınızı ayarlayın:
184
185
 
185
186
  #### Kök 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
  ```
@@ -310,9 +342,34 @@ Uygulamanız boyunca içerik sözlüklerinize erişin:
310
342
 
311
343
  #### Yerelleştirilmiş Ana Sayfa
312
344
 
313
- ```tsx fileName="app/routes/[lang]/page.tsx"
345
+ ```tsx fileName="app/routes/page.tsx"
346
+ import { getIntlayer, validatePrefix } from "intlayer";
314
347
  import { useIntlayer } from "react-intlayer";
315
- import { LocalizedLink } from "~/components/localized-link";
348
+ import { data } from "react-router";
349
+
350
+ import { LocaleSwitcher } from "~/components/locale-switcher";
351
+
352
+ import { Navbar } from "~/components/navbar";
353
+ import type { Route } from "./+types/page";
354
+
355
+ export const loader = ({ params }: Route.LoaderArgs) => {
356
+ const { locale } = params;
357
+
358
+ const { isValid } = validatePrefix(locale);
359
+
360
+ if (!isValid) {
361
+ throw data("Locale not supported", { status: 404 });
362
+ }
363
+ };
364
+
365
+ export const meta: Route.MetaFunction = ({ params }) => {
366
+ const content = getIntlayer("page", params.locale);
367
+
368
+ return [
369
+ { title: content.title },
370
+ { content: content.description, name: "description" },
371
+ ];
372
+ };
316
373
 
317
374
  export default function Page() {
318
375
  const { title, description, aboutLink } = useIntlayer("page");
@@ -31,6 +31,8 @@ history:
31
31
 
32
32
  Bu rehber, React Router v7 projelerinde **dosya sistemi tabanlı yönlendirme** (`@react-router/fs-routes`) kullanarak yerel dil farkındalıklı yönlendirme, TypeScript desteği ve modern geliştirme uygulamaları ile sorunsuz uluslararasılaştırma için **Intlayer**'ın nasıl entegre edileceğini gösterir.
33
33
 
34
+ İstemci tarafı yönlendirme için, [Intlayer ile React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/tr/intlayer_with_react_router_v7.md) rehberine bakın.
35
+
34
36
  ## Table of Contents
35
37
 
36
38
  <TOC/>
@@ -195,12 +197,13 @@ Dosya sistemi yönlendirmesi ile, noktalar (`.`) yol segmentlerini temsil eden v
195
197
  #### Dosya Yapısı
196
198
 
197
199
  ```bash
198
- app/routes/
199
- ├── ($locale)._layout.tsx # Yerel rota için layout sarmalayıcı
200
- ├── ($locale)._index.tsx # Ana sayfa (/:locale?)
201
- ├── ($locale)._index.content.ts # Ana sayfa içeriği
202
- ├── ($locale).about.tsx # Hakkında sayfası (/:locale?/about)
203
- └── ($locale).about.content.ts # Hakkında sayfası içeriği
200
+ app/
201
+ ├── root.tsx # Yerel rota için layout sarmalayıcı
202
+ └──routes/
203
+ ├── ($locale)._index.tsx # Ana sayfa (/, /es, vb.)
204
+ ├── ($locale)._index.content.ts # Ana sayfa içeriği
205
+ ├── ($locale).about.tsx # Hakkında sayfası (/about, /es/about, vb.)
206
+ └── ($locale).about.content.ts # Hakkında sayfası içeriği
204
207
  ```
205
208
 
206
209
  Adlandırma kuralları:
@@ -212,23 +215,50 @@ Adlandırma kuralları:
212
215
 
213
216
  #### Layout Bileşeni
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
  #### İndeks Sayfası
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
  #### Hakkında Sayfası
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
 
@@ -484,7 +560,7 @@ export const useI18nHTMLAttributes = () => {
484
560
  };
485
561
  ```
486
562
 
487
- Bu hook, Adım 5'te gösterilen layout bileşeninde (`($locale)._layout.tsx`) zaten kullanılmaktadır.
563
+ Bu hook, Adım 5'te gösterilen layout bileşeninde (`root.tsx`) zaten kullanılmaktadır.
488
564
 
489
565
  ### Adım 10: Middleware ekleyin (İsteğe bağlı)
490
566
 
@@ -553,15 +553,15 @@ Intlayer giúp bạn giữ đồng bộ các bản dịch JSON, kiểm tra các
553
553
  Cài đặt các dependencies của 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
  Cài đặt các phụ thuộc của 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
  Tạo file cấu hình intlayer: