@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: Intlayerを使用してReact Router v7アプリケーションに国際化(i18n)を追加する方法を学びます。ロケール対応ルーティングでアプリを多言語化するための包括的なガイドに従ってください。
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: ドキュメント更新
@@ -172,10 +175,8 @@ export default defineConfig({
172
175
  import { layout, route, type RouteConfig } from "@react-router/dev/routes";
173
176
 
174
177
  export default [
175
- layout("routes/layout.tsx", [
176
- route("/:lang?", "routes/page.tsx"), // ローカライズされたホームページ
177
- route("/:lang?/about", "routes/about/page.tsx"), // ローカライズされたアバウトページ
178
- ]),
178
+ route("/:lang?", "routes/page.tsx"), // ローカライズされたホームページ
179
+ route("/:lang?/about", "routes/about/page.tsx"), // ローカライズされたアバウトページ
179
180
  ] satisfies RouteConfig;
180
181
  ```
181
182
 
@@ -185,19 +186,50 @@ export default [
185
186
 
186
187
  #### ルートレイアウト
187
188
 
188
- ```tsx fileName="app/routes/layout.tsx"
189
+ ```tsx fileName="app/root.tsx"
190
+ import { getLocaleFromPath } from "intlayer";
189
191
  import { IntlayerProvider } from "react-intlayer";
190
- 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";
191
200
 
192
- import type { Route } from "./+types/layout";
201
+ // ... Unchanged App, links and ErrorBoundary code
193
202
 
194
- export default function RootLayout({ params }: Route.ComponentProps) {
195
- 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 ?? {};
196
218
 
197
219
  return (
198
- <IntlayerProvider locale={locale}>
199
- <Outlet />
200
- </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>
201
233
  );
202
234
  }
203
235
  ```
@@ -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
  このガイドでは、React Router v7プロジェクトにおいて、**ファイルシステムベースのルーティング**(`@react-router/fs-routes`)を使用して、ロケール対応ルーティング、TypeScriptサポート、最新の開発手法を活用しながら、**Intlayer**を使ったシームレスな国際化の統合方法を説明します。
33
33
 
34
+ クライアントサイドルーティングについては、[IntlayerとReact Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/intlayer_with_react_router_v7.md)ガイドを参照してください。
35
+
34
36
  ## Table of Contents
35
37
 
36
38
  <TOC/>
@@ -196,12 +198,13 @@ export default routes;
196
198
  #### ファイル構造
197
199
 
198
200
  ```bash
199
- app/routes/
200
- ├── ($locale)._layout.tsx # ロケールルートのレイアウトラッパー
201
- ├── ($locale)._index.tsx # ホームページ (/:locale?)
202
- ├── ($locale)._index.content.ts # ホームページのコンテンツ
203
- ├── ($locale).about.tsx # アバウトページ (/:locale?/about)
204
- └── ($locale).about.content.ts # アバウトページのコンテンツ
201
+ app/
202
+ ├── root.tsx # ロケールルートのレイアウトラッパー
203
+ └──routes/
204
+ ├── ($locale)._index.tsx # ホームページ (/, /es, など)
205
+ ├── ($locale)._index.content.ts # ホームページのコンテンツ
206
+ ├── ($locale).about.tsx # アバウトページ (/about, /es/about, など)
207
+ └── ($locale).about.content.ts # アバウトページのコンテンツ
205
208
  ```
206
209
 
207
210
  命名規則:
@@ -213,23 +216,50 @@ app/routes/
213
216
 
214
217
  #### レイアウトコンポーネント
215
218
 
216
- ```tsx fileName="app/routes/($locale)._layout.tsx"
219
+ ```tsx fileName="app/root.tsx"
220
+ import { getLocaleFromPath } from "intlayer";
217
221
  import { IntlayerProvider } from "react-intlayer";
218
- import { Outlet } from "react-router";
222
+ import {
223
+ isRouteErrorResponse,
224
+ Meta,
225
+ Outlet,
226
+ Scripts,
227
+ ScrollRestoration,
228
+ useLoaderData,
229
+ } from "react-router";
219
230
 
220
- import { useI18nHTMLAttributes } from "~/hooks/useI18nHTMLAttributes";
231
+ import type { Route } from "./+types/root";
221
232
 
222
- import type { Route } from "./+types/($locale)._layout";
233
+ import "./app.css";
223
234
 
224
- export default function RootLayout({ params }: Route.ComponentProps) {
225
- useI18nHTMLAttributes();
235
+ // links and ErrorBoundary code
226
236
 
227
- const { locale } = params;
237
+ export async function loader({ request }: Route.LoaderArgs) {
238
+ const locale = getLocaleFromPath(request.url);
239
+
240
+ return { locale };
241
+ }
242
+
243
+ export function Layout({
244
+ children,
245
+ }: { children: React.ReactNode } & Route.ComponentProps) {
246
+ const data = useLoaderData<typeof loader>();
247
+ const { locale } = data ?? {};
228
248
 
229
249
  return (
230
- <IntlayerProvider locale={locale}>
231
- <Outlet />
232
- </IntlayerProvider>
250
+ <html lang={locale}>
251
+ <head>
252
+ <meta charSet="utf-8" />
253
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
254
+ <Meta />
255
+ <Links />
256
+ </head>
257
+ <body>
258
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
259
+ <ScrollRestoration />
260
+ <Scripts />
261
+ </body>
262
+ </html>
233
263
  );
234
264
  }
235
265
  ```
@@ -237,11 +267,34 @@ export default function RootLayout({ params }: Route.ComponentProps) {
237
267
  #### インデックスページ
238
268
 
239
269
  ```tsx fileName="app/routes/($locale)._index.tsx"
270
+ import { getIntlayer, validatePrefix } from "intlayer";
240
271
  import { useIntlayer } from "react-intlayer";
241
- import { LocalizedLink } from "~/components/localized-link";
272
+ import { data } from "react-router";
273
+
274
+ import { LocaleSwitcher } from "~/components/locale-switcher";
275
+ import { Navbar } from "~/components/navbar";
242
276
 
243
277
  import type { Route } from "./+types/($locale)._index";
244
278
 
279
+ export const loader = ({ params }: Route.LoaderArgs) => {
280
+ const { locale } = params;
281
+
282
+ const { isValid } = validatePrefix(locale);
283
+
284
+ if (!isValid) {
285
+ throw data("Locale not supported", { status: 404 });
286
+ }
287
+ };
288
+
289
+ export const meta: Route.MetaFunction = ({ params }) => {
290
+ const content = getIntlayer("page", params.locale);
291
+
292
+ return [
293
+ { title: content.title },
294
+ { content: content.description, name: "description" },
295
+ ];
296
+ };
297
+
245
298
  export default function Page() {
246
299
  const { title, description, aboutLink } = useIntlayer("page");
247
300
 
@@ -260,11 +313,34 @@ export default function Page() {
260
313
  #### アバウトページ
261
314
 
262
315
  ```tsx fileName="app/routes/($locale).about.tsx"
316
+ import { getIntlayer, validatePrefix } from "intlayer";
263
317
  import { useIntlayer } from "react-intlayer";
264
- import { LocalizedLink } from "~/components/localized-link";
318
+ import { data } from "react-router";
319
+
320
+ import { LocaleSwitcher } from "~/components/locale-switcher";
321
+ import { Navbar } from "~/components/navbar";
265
322
 
266
323
  import type { Route } from "./+types/($locale).about";
267
324
 
325
+ export const loader = ({ params }: Route.LoaderArgs) => {
326
+ const { locale } = params;
327
+
328
+ const { isValid } = validatePrefix(locale);
329
+
330
+ if (!isValid) {
331
+ throw data("Locale not supported", { status: 404 });
332
+ }
333
+ };
334
+
335
+ export const meta: Route.MetaFunction = ({ params }) => {
336
+ const content = getIntlayer("about", params.locale);
337
+
338
+ return [
339
+ { title: content.title },
340
+ { content: content.description, name: "description" },
341
+ ];
342
+ };
343
+
268
344
  export default function AboutPage() {
269
345
  const { title, content, homeLink } = useIntlayer("about");
270
346
 
@@ -486,7 +562,7 @@ export const useI18nHTMLAttributes = () => {
486
562
  };
487
563
  ```
488
564
 
489
- このフックは、ステップ5で示したレイアウトコンポーネント(`($locale)._layout.tsx`)で既に使用されています。
565
+ このフックは、ステップ5で示したレイアウトコンポーネント(`root.tsx`)で既に使用されています。
490
566
 
491
567
  ### ステップ10: ミドルウェアを追加する(オプション)
492
568
 
@@ -552,15 +552,15 @@ Intlayer는 JSON 번역을 동기화 상태로 유지하고, 누락된 키를
552
552
  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
  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)를 추가하는 방법을 배우세요. 로케일 인식 라우팅으로 앱을 다국어로 만드는 종합 가이드를 따르세요.
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: 문서 업데이트
@@ -172,10 +175,8 @@ export default defineConfig({
172
175
  import { layout, route, type RouteConfig } from "@react-router/dev/routes";
173
176
 
174
177
  export default [
175
- layout("routes/layout.tsx", [
176
- route("/:lang?", "routes/page.tsx"), // 지역화된 페이지
177
- route("/:lang?/about", "routes/about/page.tsx"), // 지역화된 소개 페이지
178
- ]),
178
+ route("/:lang?", "routes/page.tsx"), // 지역화된 홈 페이지
179
+ route("/:lang?/about", "routes/about/page.tsx"), // 지역화된 소개 페이지
179
180
  ] satisfies RouteConfig;
180
181
  ```
181
182
 
@@ -185,19 +186,50 @@ export default [
185
186
 
186
187
  #### 루트 레이아웃
187
188
 
188
- ```tsx fileName="app/routes/layout.tsx"
189
+ ```tsx fileName="app/root.tsx"
190
+ import { getLocaleFromPath } from "intlayer";
189
191
  import { IntlayerProvider } from "react-intlayer";
190
- 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";
191
200
 
192
- import type { Route } from "./+types/layout";
201
+ // ... Unchanged App, links and ErrorBoundary code
193
202
 
194
- export default function RootLayout({ params }: Route.ComponentProps) {
195
- 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 ?? {};
196
218
 
197
219
  return (
198
- <IntlayerProvider locale={locale}>
199
- <Outlet />
200
- </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>
201
233
  );
202
234
  }
203
235
  ```
@@ -310,9 +342,34 @@ export const useLocalizedNavigate = () => {
310
342
 
311
343
  #### 현지화된 홈 페이지
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");
@@ -32,6 +32,8 @@ history:
32
32
 
33
33
  이 가이드는 React Router v7 프로젝트에서 로케일 인식 라우팅, TypeScript 지원 및 최신 개발 방식을 활용하여 **Intlayer**를 통합해 원활한 국제화(i18n)를 구현하는 방법을 보여줍니다.
34
34
 
35
+ 클라이언트 사이드 라우팅의 경우 [Intlayer와 React Router v7](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_with_react_router_v7.md) 가이드를 참조하세요.
36
+
35
37
  ## Table of Contents
36
38
 
37
39
  <TOC/>
@@ -553,15 +553,15 @@ Intlayer pomaga utrzymać synchronizację tłumaczeń JSON, testować brakujące
553
553
  Zainstaluj zależności 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
  Zainstaluj zależności 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
  Utwórz plik konfiguracyjny 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: Jak przetłumaczyć aplikację React Router v7 – przewodnik i18n 2025
5
5
  description: Dowiedz się, jak dodać internacjonalizację (i18n) do swojej aplikacji React Router v7 za pomocą Intlayer. Postępuj zgodnie z tym kompleksowym przewodnikiem, aby uczynić swoją aplikację wielojęzyczną z routingiem uwzględniającym lokalizację.
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: Zaktualizuj Layout i obsłuż 404
23
26
  - version: 6.1.5
24
27
  date: 2025-10-03
25
28
  changes: Zaktualizowano dokumentację
@@ -183,10 +186,8 @@ Skonfiguruj routing z trasami uwzględniającymi lokalizację:
183
186
  import { layout, route, type RouteConfig } from "@react-router/dev/routes";
184
187
 
185
188
  export default [
186
- layout("routes/layout.tsx", [
187
- route("/:lang?", "routes/page.tsx"), // Lokalizowana strona główna
188
- route("/:lang?/about", "routes/about/page.tsx"), // Lokalizowana strona o nas
189
- ]),
189
+ route("/:lang?", "routes/page.tsx"), // Lokalizowana strona główna
190
+ route("/:lang?/about", "routes/about/page.tsx"), // Lokalizowana strona o nas
190
191
  ] satisfies RouteConfig;
191
192
  ```
192
193
 
@@ -196,19 +197,50 @@ Skonfiguruj swój główny layout oraz layouty specyficzne dla lokalizacji:
196
197
 
197
198
  #### Główny Layout
198
199
 
199
- ```tsx fileName="app/routes/layout.tsx"
200
+ ```tsx fileName="app/root.tsx"
201
+ import { getLocaleFromPath } from "intlayer";
200
202
  import { IntlayerProvider } from "react-intlayer";
201
- import { Outlet } from "react-router";
203
+ import {
204
+ data,
205
+ Meta,
206
+ Scripts,
207
+ ScrollRestoration,
208
+ useLoaderData,
209
+ } from "react-router";
210
+ import type { Route } from "./+types/root";
211
+
212
+ // ... Unchanged App, links and ErrorBoundary code
213
+
214
+ export async function loader({ request }: Route.LoaderArgs) {
215
+ const locale = getLocaleFromPath(request.url);
202
216
 
203
- import type { Route } from "./+types/layout";
217
+ if (!locale) {
218
+ throw data("Language not supported", { status: 404 });
219
+ }
220
+
221
+ return { locale };
222
+ }
204
223
 
205
- export default function RootLayout({ params }: Route.ComponentProps) {
206
- const { locale } = params;
224
+ export function Layout({
225
+ children,
226
+ }: { children: React.ReactNode } & Route.ComponentProps) {
227
+ const data = useLoaderData<typeof loader>();
228
+ const { locale } = data ?? {};
207
229
 
208
230
  return (
209
- <IntlayerProvider locale={locale}>
210
- <Outlet />
211
- </IntlayerProvider>
231
+ <html lang={locale}>
232
+ <head>
233
+ <meta charSet="utf-8" />
234
+ <meta content="width=device-width, initial-scale=1" name="viewport" />
235
+ <Meta />
236
+ <Links />
237
+ </head>
238
+ <body>
239
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
240
+ <ScrollRestoration />
241
+ <Scripts />
242
+ </body>
243
+ </html>
212
244
  );
213
245
  }
214
246
  ```