@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.
- package/blog/ar/intlayer_with_i18next.md +4 -4
- package/blog/ar/intlayer_with_next-i18next.md +4 -4
- package/blog/ar/intlayer_with_next-intl.md +4 -4
- package/blog/ar/intlayer_with_react-i18next.md +4 -4
- package/blog/ar/intlayer_with_react-intl.md +4 -4
- package/blog/ar/intlayer_with_vue-i18n.md +4 -4
- package/blog/de/intlayer_with_i18next.md +4 -4
- package/blog/de/intlayer_with_next-i18next.md +4 -4
- package/blog/de/intlayer_with_next-intl.md +4 -4
- package/blog/de/intlayer_with_react-i18next.md +4 -4
- package/blog/de/intlayer_with_react-intl.md +4 -4
- package/blog/de/intlayer_with_vue-i18n.md +4 -4
- package/blog/en/intlayer_with_i18next.md +4 -4
- package/blog/en/intlayer_with_next-i18next.md +4 -4
- package/blog/en/intlayer_with_next-intl.md +4 -4
- package/blog/en/intlayer_with_react-i18next.md +4 -4
- package/blog/en/intlayer_with_react-intl.md +4 -4
- package/blog/en/intlayer_with_vue-i18n.md +4 -4
- package/blog/en-GB/intlayer_with_i18next.md +4 -4
- package/blog/en-GB/intlayer_with_next-i18next.md +4 -4
- package/blog/en-GB/intlayer_with_next-intl.md +4 -4
- package/blog/en-GB/intlayer_with_react-i18next.md +4 -4
- package/blog/en-GB/intlayer_with_react-intl.md +4 -4
- package/blog/en-GB/intlayer_with_vue-i18n.md +4 -4
- package/blog/es/intlayer_with_i18next.md +4 -4
- package/blog/es/intlayer_with_next-i18next.md +4 -4
- package/blog/es/intlayer_with_next-intl.md +4 -4
- package/blog/es/intlayer_with_react-i18next.md +4 -4
- package/blog/es/intlayer_with_react-intl.md +4 -4
- package/blog/es/intlayer_with_vue-i18n.md +4 -4
- package/blog/fr/intlayer_with_i18next.md +4 -4
- package/blog/fr/intlayer_with_next-i18next.md +4 -4
- package/blog/fr/intlayer_with_next-intl.md +4 -4
- package/blog/fr/intlayer_with_react-i18next.md +4 -4
- package/blog/fr/intlayer_with_react-intl.md +4 -4
- package/blog/fr/intlayer_with_vue-i18n.md +4 -4
- package/blog/hi/intlayer_with_i18next.md +4 -4
- package/blog/hi/intlayer_with_next-i18next.md +4 -4
- package/blog/hi/intlayer_with_next-intl.md +4 -4
- package/blog/hi/intlayer_with_react-i18next.md +4 -4
- package/blog/hi/intlayer_with_react-intl.md +4 -4
- package/blog/hi/intlayer_with_vue-i18n.md +4 -4
- package/blog/id/intlayer_with_i18next.md +4 -4
- package/blog/id/intlayer_with_next-i18next.md +4 -4
- package/blog/id/intlayer_with_next-intl.md +4 -4
- package/blog/id/intlayer_with_react-i18next.md +4 -4
- package/blog/id/intlayer_with_react-intl.md +4 -4
- package/blog/id/intlayer_with_vue-i18n.md +4 -4
- package/blog/it/intlayer_with_i18next.md +4 -4
- package/blog/it/intlayer_with_next-i18next.md +4 -4
- package/blog/it/intlayer_with_next-intl.md +4 -4
- package/blog/it/intlayer_with_react-i18next.md +4 -4
- package/blog/it/intlayer_with_react-intl.md +4 -4
- package/blog/it/intlayer_with_vue-i18n.md +4 -4
- package/blog/ja/intlayer_with_i18next.md +4 -4
- package/blog/ja/intlayer_with_next-i18next.md +4 -4
- package/blog/ja/intlayer_with_next-intl.md +4 -4
- package/blog/ja/intlayer_with_react-i18next.md +4 -4
- package/blog/ja/intlayer_with_react-intl.md +4 -4
- package/blog/ja/intlayer_with_vue-i18n.md +4 -4
- package/blog/ko/intlayer_with_i18next.md +4 -4
- package/blog/ko/intlayer_with_next-i18next.md +4 -4
- package/blog/ko/intlayer_with_next-intl.md +4 -4
- package/blog/ko/intlayer_with_react-i18next.md +4 -4
- package/blog/ko/intlayer_with_react-intl.md +4 -4
- package/blog/ko/intlayer_with_vue-i18n.md +4 -4
- package/blog/pl/intlayer_with_i18next.md +4 -4
- package/blog/pl/intlayer_with_next-i18next.md +4 -4
- package/blog/pl/intlayer_with_next-intl.md +4 -4
- package/blog/pl/intlayer_with_react-i18next.md +4 -4
- package/blog/pl/intlayer_with_react-intl.md +4 -4
- package/blog/pl/intlayer_with_vue-i18n.md +4 -4
- package/blog/pt/intlayer_with_i18next.md +4 -4
- package/blog/pt/intlayer_with_next-i18next.md +4 -4
- package/blog/pt/intlayer_with_next-intl.md +4 -4
- package/blog/pt/intlayer_with_react-i18next.md +4 -4
- package/blog/pt/intlayer_with_react-intl.md +4 -4
- package/blog/pt/intlayer_with_vue-i18n.md +4 -4
- package/blog/ru/intlayer_with_i18next.md +4 -4
- package/blog/ru/intlayer_with_next-i18next.md +4 -4
- package/blog/ru/intlayer_with_next-intl.md +4 -4
- package/blog/ru/intlayer_with_react-i18next.md +4 -4
- package/blog/ru/intlayer_with_react-intl.md +4 -4
- package/blog/ru/intlayer_with_vue-i18n.md +4 -4
- package/blog/tr/intlayer_with_i18next.md +4 -4
- package/blog/tr/intlayer_with_next-i18next.md +4 -4
- package/blog/tr/intlayer_with_next-intl.md +4 -4
- package/blog/tr/intlayer_with_react-i18next.md +4 -4
- package/blog/tr/intlayer_with_react-intl.md +4 -4
- package/blog/tr/intlayer_with_vue-i18n.md +4 -4
- package/blog/vi/intlayer_with_i18next.md +4 -4
- package/blog/vi/intlayer_with_next-i18next.md +4 -4
- package/blog/vi/intlayer_with_next-intl.md +4 -4
- package/blog/vi/intlayer_with_react-i18next.md +4 -4
- package/blog/vi/intlayer_with_react-intl.md +4 -4
- package/blog/vi/intlayer_with_vue-i18n.md +4 -4
- package/blog/zh/intlayer_with_i18next.md +4 -4
- package/blog/zh/intlayer_with_next-i18next.md +4 -4
- package/blog/zh/intlayer_with_next-intl.md +4 -4
- package/blog/zh/intlayer_with_react-i18next.md +4 -4
- package/blog/zh/intlayer_with_react-intl.md +4 -4
- package/blog/zh/intlayer_with_vue-i18n.md +4 -4
- package/docs/ar/intlayer_with_next-i18next.md +3 -3
- package/docs/ar/intlayer_with_next-intl.md +3 -3
- package/docs/ar/intlayer_with_react_router_v7.md +72 -16
- package/docs/ar/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/de/intlayer_with_next-i18next.md +3 -3
- package/docs/de/intlayer_with_next-intl.md +3 -3
- package/docs/de/intlayer_with_react_router_v7.md +72 -15
- package/docs/de/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/en/configuration.md +1 -0
- package/docs/en/intlayer_with_next-i18next.md +3 -3
- package/docs/en/intlayer_with_next-intl.md +3 -3
- package/docs/en/intlayer_with_react_router_v7.md +74 -15
- package/docs/en/intlayer_with_react_router_v7_fs_routes.md +98 -19
- package/docs/en-GB/configuration.md +1 -0
- package/docs/en-GB/intlayer_with_next-i18next.md +3 -3
- package/docs/en-GB/intlayer_with_next-intl.md +3 -3
- package/docs/en-GB/intlayer_with_react_router_v7.md +73 -16
- package/docs/en-GB/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/es/intlayer_with_next-i18next.md +3 -3
- package/docs/es/intlayer_with_next-intl.md +3 -3
- package/docs/es/intlayer_with_react_router_v7.md +72 -15
- package/docs/es/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/fr/intlayer_with_next-i18next.md +3 -3
- package/docs/fr/intlayer_with_next-intl.md +3 -3
- package/docs/fr/intlayer_with_react_router_v7.md +72 -15
- package/docs/fr/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/hi/intlayer_with_next-i18next.md +3 -3
- package/docs/hi/intlayer_with_next-intl.md +3 -3
- package/docs/hi/intlayer_with_react_router_v7.md +72 -16
- package/docs/hi/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/id/intlayer_with_next-i18next.md +3 -3
- package/docs/id/intlayer_with_next-intl.md +3 -3
- package/docs/id/intlayer_with_react_router_v7.md +72 -15
- package/docs/id/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/it/intlayer_with_next-i18next.md +3 -3
- package/docs/it/intlayer_with_next-intl.md +3 -3
- package/docs/it/intlayer_with_react_router_v7.md +72 -15
- package/docs/it/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/ja/intlayer_with_next-i18next.md +3 -3
- package/docs/ja/intlayer_with_next-intl.md +3 -3
- package/docs/ja/intlayer_with_react_router_v7.md +72 -15
- package/docs/ja/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/ko/intlayer_with_next-i18next.md +3 -3
- package/docs/ko/intlayer_with_next-intl.md +3 -3
- package/docs/ko/intlayer_with_react_router_v7.md +72 -15
- package/docs/ko/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/pl/intlayer_with_next-i18next.md +3 -3
- package/docs/pl/intlayer_with_next-intl.md +3 -3
- package/docs/pl/intlayer_with_react_router_v7.md +45 -13
- package/docs/pl/intlayer_with_react_router_v7_fs_routes.md +94 -18
- package/docs/pt/intlayer_with_next-i18next.md +3 -3
- package/docs/pt/intlayer_with_next-intl.md +3 -3
- package/docs/pt/intlayer_with_react_router_v7.md +79 -46
- package/docs/pt/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/ru/intlayer_with_next-i18next.md +3 -3
- package/docs/ru/intlayer_with_next-intl.md +3 -3
- package/docs/ru/intlayer_with_react_router_v7.md +72 -15
- package/docs/ru/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/tr/intlayer_with_next-i18next.md +3 -3
- package/docs/tr/intlayer_with_next-intl.md +3 -3
- package/docs/tr/intlayer_with_react_router_v7.md +72 -15
- package/docs/tr/intlayer_with_react_router_v7_fs_routes.md +95 -19
- package/docs/vi/intlayer_with_next-i18next.md +3 -3
- package/docs/vi/intlayer_with_next-intl.md +3 -3
- package/docs/vi/intlayer_with_react_router_v7.md +72 -15
- package/docs/vi/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/docs/zh/intlayer_with_next-i18next.md +3 -3
- package/docs/zh/intlayer_with_next-intl.md +3 -3
- package/docs/zh/intlayer_with_react_router_v7.md +72 -15
- package/docs/zh/intlayer_with_react_router_v7_fs_routes.md +2 -0
- package/package.json +6 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-09-04
|
|
3
|
-
updatedAt: 2025-
|
|
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
|
-
|
|
177
|
-
|
|
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/
|
|
190
|
+
```tsx fileName="app/root.tsx"
|
|
191
|
+
import { getLocaleFromPath } from "intlayer";
|
|
190
192
|
import { IntlayerProvider } from "react-intlayer";
|
|
191
|
-
import {
|
|
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
|
-
|
|
202
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
194
203
|
|
|
195
|
-
export
|
|
196
|
-
const
|
|
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
|
-
<
|
|
200
|
-
<
|
|
201
|
-
|
|
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/
|
|
347
|
+
```tsx fileName="app/routes/page.tsx"
|
|
348
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
316
349
|
import { useIntlayer } from "react-intlayer";
|
|
317
|
-
import {
|
|
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/
|
|
201
|
-
├──
|
|
202
|
-
|
|
203
|
-
├── ($locale)._index.
|
|
204
|
-
├── ($locale).
|
|
205
|
-
|
|
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/
|
|
220
|
+
```tsx fileName="app/root.tsx"
|
|
221
|
+
import { getLocaleFromPath } from "intlayer";
|
|
218
222
|
import { IntlayerProvider } from "react-intlayer";
|
|
219
|
-
import {
|
|
223
|
+
import {
|
|
224
|
+
isRouteErrorResponse,
|
|
225
|
+
Meta,
|
|
226
|
+
Outlet,
|
|
227
|
+
Scripts,
|
|
228
|
+
ScrollRestoration,
|
|
229
|
+
useLoaderData,
|
|
230
|
+
} from "react-router";
|
|
220
231
|
|
|
221
|
-
import {
|
|
232
|
+
import type { Route } from "./+types/root";
|
|
222
233
|
|
|
223
|
-
import
|
|
234
|
+
import "./app.css";
|
|
224
235
|
|
|
225
|
-
|
|
226
|
-
useI18nHTMLAttributes();
|
|
236
|
+
// links and ErrorBoundary code
|
|
227
237
|
|
|
228
|
-
|
|
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
|
-
<
|
|
232
|
-
<
|
|
233
|
-
|
|
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 {
|
|
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 {
|
|
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 (`
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
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
|
-
|
|
175
|
-
|
|
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/
|
|
188
|
+
```tsx fileName="app/root.tsx"
|
|
189
|
+
import { getLocaleFromPath } from "intlayer";
|
|
188
190
|
import { IntlayerProvider } from "react-intlayer";
|
|
189
|
-
import {
|
|
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
|
-
|
|
200
|
+
// ... Unchanged App, links and ErrorBoundary code
|
|
192
201
|
|
|
193
|
-
export
|
|
194
|
-
const
|
|
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
|
-
<
|
|
198
|
-
<
|
|
199
|
-
|
|
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/
|
|
345
|
+
```tsx fileName="app/routes/page.tsx"
|
|
346
|
+
import { getIntlayer, validatePrefix } from "intlayer";
|
|
314
347
|
import { useIntlayer } from "react-intlayer";
|
|
315
|
-
import {
|
|
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/
|
|
199
|
-
├──
|
|
200
|
-
|
|
201
|
-
├── ($locale)._index.
|
|
202
|
-
├── ($locale).
|
|
203
|
-
|
|
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/
|
|
218
|
+
```tsx fileName="app/root.tsx"
|
|
219
|
+
import { getLocaleFromPath } from "intlayer";
|
|
216
220
|
import { IntlayerProvider } from "react-intlayer";
|
|
217
|
-
import {
|
|
221
|
+
import {
|
|
222
|
+
isRouteErrorResponse,
|
|
223
|
+
Meta,
|
|
224
|
+
Outlet,
|
|
225
|
+
Scripts,
|
|
226
|
+
ScrollRestoration,
|
|
227
|
+
useLoaderData,
|
|
228
|
+
} from "react-router";
|
|
218
229
|
|
|
219
|
-
import {
|
|
230
|
+
import type { Route } from "./+types/root";
|
|
220
231
|
|
|
221
|
-
import
|
|
232
|
+
import "./app.css";
|
|
222
233
|
|
|
223
|
-
|
|
224
|
-
useI18nHTMLAttributes();
|
|
234
|
+
// links and ErrorBoundary code
|
|
225
235
|
|
|
226
|
-
|
|
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
|
-
<
|
|
230
|
-
<
|
|
231
|
-
|
|
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 {
|
|
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 {
|
|
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 (`
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
402
|
+
pnpm add intlayer @intlayer/sync-json-plugin --save-dev
|
|
403
403
|
```
|
|
404
404
|
|
|
405
405
|
Tạo file cấu hình intlayer:
|