@intlayer/docs 5.7.6 → 5.7.8
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/dist/cjs/generated/docs.entry.cjs +44 -238
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +44 -238
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +1 -2
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/CI_CD.md +67 -41
- package/docs/ar/intlayer_with_tanstack.md +457 -0
- package/docs/ar/packages/next-intlayer/index.md +0 -1
- package/docs/ar/packages/react-intlayer/index.md +0 -1
- package/docs/de/CI_CD.md +63 -37
- package/docs/de/intlayer_with_tanstack.md +458 -0
- package/docs/de/packages/next-intlayer/index.md +0 -1
- package/docs/de/packages/react-intlayer/index.md +0 -1
- package/docs/en/CI_CD.md +51 -27
- package/docs/en/intlayer_with_tanstack.md +452 -0
- package/docs/en/packages/next-intlayer/index.md +0 -1
- package/docs/en/packages/react-intlayer/index.md +0 -1
- package/docs/en-GB/CI_CD.md +58 -32
- package/docs/en-GB/intlayer_with_tanstack.md +457 -0
- package/docs/en-GB/packages/next-intlayer/index.md +0 -1
- package/docs/en-GB/packages/react-intlayer/index.md +0 -1
- package/docs/es/CI_CD.md +68 -42
- package/docs/es/intlayer_with_tanstack.md +435 -0
- package/docs/es/packages/next-intlayer/index.md +0 -1
- package/docs/es/packages/react-intlayer/index.md +0 -1
- package/docs/fr/intlayer_with_tanstack.md +435 -0
- package/docs/fr/packages/next-intlayer/index.md +0 -1
- package/docs/fr/packages/react-intlayer/index.md +0 -1
- package/docs/hi/CI_CD.md +69 -44
- package/docs/hi/intlayer_with_tanstack.md +438 -0
- package/docs/hi/packages/next-intlayer/index.md +0 -1
- package/docs/hi/packages/react-intlayer/index.md +0 -1
- package/docs/it/CI_CD.md +67 -41
- package/docs/it/intlayer_with_tanstack.md +457 -0
- package/docs/it/packages/next-intlayer/index.md +0 -1
- package/docs/it/packages/react-intlayer/index.md +0 -1
- package/docs/ja/CI_CD.md +67 -41
- package/docs/ja/intlayer_with_tanstack.md +457 -0
- package/docs/ja/packages/next-intlayer/index.md +0 -1
- package/docs/ja/packages/react-intlayer/index.md +0 -1
- package/docs/ko/CI_CD.md +63 -37
- package/docs/ko/intlayer_with_tanstack.md +457 -0
- package/docs/ko/packages/next-intlayer/index.md +0 -1
- package/docs/ko/packages/react-intlayer/index.md +0 -1
- package/docs/pt/CI_CD.md +67 -41
- package/docs/pt/intlayer_with_tanstack.md +457 -0
- package/docs/pt/packages/next-intlayer/index.md +0 -1
- package/docs/pt/packages/react-intlayer/index.md +0 -1
- package/docs/ru/CI_CD.md +70 -44
- package/docs/ru/intlayer_with_tanstack.md +458 -0
- package/docs/ru/packages/next-intlayer/index.md +0 -1
- package/docs/ru/packages/react-intlayer/index.md +0 -1
- package/docs/zh/CI_CD.md +62 -36
- package/docs/zh/intlayer_with_tanstack.md +435 -0
- package/docs/zh/packages/next-intlayer/index.md +0 -1
- package/docs/zh/packages/react-intlayer/index.md +0 -1
- package/package.json +9 -9
- package/src/generated/docs.entry.ts +44 -238
- package/docs/ar/packages/next-intlayer/useIntlayerAsync.md +0 -237
- package/docs/ar/packages/react-intlayer/useIntlayerAsync.md +0 -252
- package/docs/de/packages/next-intlayer/useIntlayerAsync.md +0 -262
- package/docs/de/packages/react-intlayer/useIntlayerAsync.md +0 -256
- package/docs/en/packages/next-intlayer/useIntlayerAsync.md +0 -239
- package/docs/en/packages/react-intlayer/useIntlayerAsync.md +0 -254
- package/docs/en-GB/packages/next-intlayer/useIntlayerAsync.md +0 -237
- package/docs/en-GB/packages/react-intlayer/useIntlayerAsync.md +0 -257
- package/docs/es/packages/next-intlayer/useIntlayerAsync.md +0 -240
- package/docs/es/packages/react-intlayer/useIntlayerAsync.md +0 -276
- package/docs/fr/packages/next-intlayer/useIntlayerAsync.md +0 -238
- package/docs/fr/packages/react-intlayer/useIntlayerAsync.md +0 -252
- package/docs/hi/packages/next-intlayer/useIntlayerAsync.md +0 -237
- package/docs/hi/packages/react-intlayer/useIntlayerAsync.md +0 -252
- package/docs/it/packages/next-intlayer/useIntlayerAsync.md +0 -237
- package/docs/it/packages/react-intlayer/useIntlayerAsync.md +0 -252
- package/docs/ja/packages/next-intlayer/useIntlayerAsync.md +0 -237
- package/docs/ja/packages/react-intlayer/useIntlayerAsync.md +0 -268
- package/docs/ko/packages/next-intlayer/useIntlayerAsync.md +0 -260
- package/docs/ko/packages/react-intlayer/useIntlayerAsync.md +0 -271
- package/docs/pt/packages/next-intlayer/useIntlayerAsync.md +0 -238
- package/docs/pt/packages/react-intlayer/useIntlayerAsync.md +0 -252
- package/docs/ru/packages/next-intlayer/useIntlayerAsync.md +0 -237
- package/docs/ru/packages/react-intlayer/useIntlayerAsync.md +0 -252
- package/docs/zh/packages/next-intlayer/useIntlayerAsync.md +0 -239
- package/docs/zh/packages/react-intlayer/useIntlayerAsync.md +0 -257
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-08-11
|
|
3
|
+
updatedAt: 2025-08-11
|
|
4
|
+
title: Erste Schritte mit Intlayer in TanStack Start (React)
|
|
5
|
+
description: Fügen Sie Ihrer TanStack Start-App mit Intlayer i18n hinzu – komponentenlokale Wörterbücher, lokalisierte URLs und SEO-freundliche Metadaten.
|
|
6
|
+
keywords:
|
|
7
|
+
- Internationalisierung
|
|
8
|
+
- Dokumentation
|
|
9
|
+
- Intlayer
|
|
10
|
+
- TanStack Start
|
|
11
|
+
- TanStack Router
|
|
12
|
+
- React
|
|
13
|
+
- i18n
|
|
14
|
+
- JavaScript
|
|
15
|
+
slugs:
|
|
16
|
+
- doc
|
|
17
|
+
- environment
|
|
18
|
+
- tanstack-start
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Erste Schritte mit der Internationalisierung (i18n) mit Intlayer und TanStack Start (React)
|
|
22
|
+
|
|
23
|
+
## Was ist Intlayer?
|
|
24
|
+
|
|
25
|
+
**Intlayer** ist ein Open-Source-i18n-Toolkit für React-Apps. Es bietet Ihnen:
|
|
26
|
+
|
|
27
|
+
- **Komponentenlokale Wörterbücher** mit TypeScript-Sicherheit.
|
|
28
|
+
- **Dynamische Metadaten & Routen** (SEO-bereit).
|
|
29
|
+
- **Laufzeit-Sprachumschaltung** (und Hilfsmittel zum Erkennen/Speichern von Sprachen).
|
|
30
|
+
- **Vite-Plugin** für Build-Zeit-Transformationen + Entwicklererlebnis (DX).
|
|
31
|
+
|
|
32
|
+
Diese Anleitung zeigt, wie man Intlayer in ein **TanStack Start**-Projekt integriert (das unter der Haube Vite und TanStack Router für Routing/SSR verwendet).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Schritt 1: Abhängigkeiten installieren
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# npm
|
|
40
|
+
npm i intlayer react-intlayer
|
|
41
|
+
npm i -D vite-intlayer
|
|
42
|
+
|
|
43
|
+
# pnpm
|
|
44
|
+
pnpm add intlayer react-intlayer
|
|
45
|
+
pnpm add -D vite-intlayer
|
|
46
|
+
|
|
47
|
+
# yarn
|
|
48
|
+
yarn add intlayer react-intlayer
|
|
49
|
+
yarn add -D vite-intlayer
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- **intlayer**: Kern (Konfiguration, Wörterbücher, CLI/Transformationen).
|
|
53
|
+
- **react-intlayer**: `<IntlayerProvider>` + Hooks für React.
|
|
54
|
+
- **vite-intlayer**: Vite-Plugin, plus optionales Middleware für Spracherkennung/-weiterleitungen (funktioniert in Entwicklung & SSR/Vorschau; für Produktions-SSR in `dependencies` verschieben).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Schritt 2: Intlayer konfigurieren
|
|
59
|
+
|
|
60
|
+
Erstellen Sie `intlayer.config.ts` im Stammverzeichnis Ihres Projekts:
|
|
61
|
+
|
|
62
|
+
```ts fileName="intlayer.config.ts"
|
|
63
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
64
|
+
|
|
65
|
+
const config: IntlayerConfig = {
|
|
66
|
+
internationalization: {
|
|
67
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
68
|
+
defaultLocale: Locales.ENGLISH,
|
|
69
|
+
},
|
|
70
|
+
// Sie können auch anpassen: contentDir, contentFileExtensions, Middleware-Optionen usw.
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default config;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
CommonJS/ESM-Varianten sind identisch zu Ihrem Originaldokument, falls Sie `cjs`/`mjs` bevorzugen.
|
|
77
|
+
|
|
78
|
+
> Vollständige Konfigurationsreferenz: siehe Intlayers Konfigurationsdokumentation.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Schritt 3: Fügen Sie das Vite-Plugin (und optional Middleware) hinzu
|
|
83
|
+
|
|
84
|
+
**TanStack Start verwendet Vite**, also fügen Sie Intlayers Plugin(s) zu Ihrer `vite.config.ts` hinzu:
|
|
85
|
+
|
|
86
|
+
```ts fileName="vite.config.ts"
|
|
87
|
+
import { defineConfig } from "vite";
|
|
88
|
+
import react from "@vitejs/plugin-react-swc";
|
|
89
|
+
import { intlayerPlugin, intLayerMiddlewarePlugin } from "vite-intlayer";
|
|
90
|
+
|
|
91
|
+
export default defineConfig({
|
|
92
|
+
plugins: [
|
|
93
|
+
react(),
|
|
94
|
+
intlayerPlugin(),
|
|
95
|
+
// Optional, aber empfohlen für die Erkennung der Sprache, Cookies & Weiterleitungen:
|
|
96
|
+
intLayerMiddlewarePlugin(),
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> Wenn Sie SSR bereitstellen, verschieben Sie `vite-intlayer` zu den `dependencies`, damit die Middleware in der Produktion ausgeführt wird.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Schritt 4: Deklarieren Sie Ihre Inhalte
|
|
106
|
+
|
|
107
|
+
Platzieren Sie Ihre Wörterbücher irgendwo unter `./src` (Standard `contentDir`). Beispiel:
|
|
108
|
+
|
|
109
|
+
```tsx fileName="src/app.content.tsx"
|
|
110
|
+
import { t, type Dictionary } from "intlayer";
|
|
111
|
+
import type { ReactNode } from "react";
|
|
112
|
+
|
|
113
|
+
const appContent = {
|
|
114
|
+
key: "app",
|
|
115
|
+
content: {
|
|
116
|
+
viteLogo: t({
|
|
117
|
+
de: "Vite-Logo",
|
|
118
|
+
en: "Vite logo",
|
|
119
|
+
fr: "Logo Vite",
|
|
120
|
+
es: "Logo Vite",
|
|
121
|
+
}),
|
|
122
|
+
reactLogo: t({
|
|
123
|
+
de: "React-Logo",
|
|
124
|
+
en: "React logo",
|
|
125
|
+
fr: "Logo React",
|
|
126
|
+
es: "Logo React",
|
|
127
|
+
}),
|
|
128
|
+
title: t({
|
|
129
|
+
de: "TanStack Start + React",
|
|
130
|
+
en: "TanStack Start + React",
|
|
131
|
+
fr: "TanStack Start + React",
|
|
132
|
+
es: "TanStack Start + React",
|
|
133
|
+
}),
|
|
134
|
+
count: t({
|
|
135
|
+
de: "Zähler ist ",
|
|
136
|
+
en: "count is ",
|
|
137
|
+
fr: "le compte est ",
|
|
138
|
+
es: "el recuento es ",
|
|
139
|
+
}),
|
|
140
|
+
edit: t<ReactNode>({
|
|
141
|
+
de: (
|
|
142
|
+
<>
|
|
143
|
+
Bearbeite <code>src/routes/index.tsx</code> und speichere, um HMR zu
|
|
144
|
+
testen
|
|
145
|
+
</>
|
|
146
|
+
),
|
|
147
|
+
en: (
|
|
148
|
+
<>
|
|
149
|
+
Edit <code>src/routes/index.tsx</code> and save to test HMR
|
|
150
|
+
</>
|
|
151
|
+
),
|
|
152
|
+
fr: (
|
|
153
|
+
<>
|
|
154
|
+
Éditez <code>src/routes/index.tsx</code> et enregistrez pour tester
|
|
155
|
+
HMR
|
|
156
|
+
</>
|
|
157
|
+
),
|
|
158
|
+
es: (
|
|
159
|
+
<>
|
|
160
|
+
Edita <code>src/routes/index.tsx</code> y guarda para probar HMR
|
|
161
|
+
</>
|
|
162
|
+
),
|
|
163
|
+
}),
|
|
164
|
+
readTheDocs: t({
|
|
165
|
+
de: "Klicken Sie auf die Logos, um mehr zu erfahren",
|
|
166
|
+
en: "Click the logos to learn more",
|
|
167
|
+
fr: "Cliquez sur les logos pour en savoir plus",
|
|
168
|
+
es: "Haz clic en los logotipos para saber más",
|
|
169
|
+
}),
|
|
170
|
+
},
|
|
171
|
+
} satisfies Dictionary;
|
|
172
|
+
|
|
173
|
+
export default appContent;
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
JSON/ESM/CJS-Varianten funktionieren genauso wie in Ihrem Originaldokument.
|
|
177
|
+
|
|
178
|
+
> TSX-Inhalt? Vergessen Sie nicht `import React from "react"`, falls Ihr Setup dies benötigt.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Schritt 5: TanStack Start mit Intlayer umschließen
|
|
183
|
+
|
|
184
|
+
Bei TanStack Start ist Ihre **Root-Route** der richtige Ort, um Provider zu setzen.
|
|
185
|
+
|
|
186
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
187
|
+
import {
|
|
188
|
+
Outlet,
|
|
189
|
+
createRootRoute,
|
|
190
|
+
Link as RouterLink,
|
|
191
|
+
} from "@tanstack/react-router";
|
|
192
|
+
import { IntlayerProvider, useIntlayer } from "react-intlayer";
|
|
193
|
+
|
|
194
|
+
function AppShell() {
|
|
195
|
+
// Beispiel für die Verwendung eines Wörterbuchs auf oberster Ebene:
|
|
196
|
+
const content = useIntlayer("app");
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<div>
|
|
200
|
+
<nav className="flex gap-3 p-3">
|
|
201
|
+
<RouterLink to="/">Startseite</RouterLink>
|
|
202
|
+
<RouterLink to="/about">Über</RouterLink>
|
|
203
|
+
</nav>
|
|
204
|
+
<main className="p-6">
|
|
205
|
+
<h1>{content.title}</h1>
|
|
206
|
+
<Outlet />
|
|
207
|
+
</main>
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export const Route = createRootRoute({
|
|
213
|
+
component: () => (
|
|
214
|
+
<IntlayerProvider>
|
|
215
|
+
<AppShell />
|
|
216
|
+
</IntlayerProvider>
|
|
217
|
+
),
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Dann verwenden Sie Ihre Inhalte in Seiten:
|
|
222
|
+
|
|
223
|
+
```tsx fileName="src/routes/index.tsx"
|
|
224
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
225
|
+
import { useIntlayer } from "react-intlayer";
|
|
226
|
+
import reactLogo from "../assets/react.svg";
|
|
227
|
+
|
|
228
|
+
export const Route = createFileRoute("/")({
|
|
229
|
+
component: () => {
|
|
230
|
+
const content = useIntlayer("app");
|
|
231
|
+
return (
|
|
232
|
+
<>
|
|
233
|
+
<button>{content.count}0</button>
|
|
234
|
+
<p>{content.edit}</p>
|
|
235
|
+
<img
|
|
236
|
+
src={reactLogo}
|
|
237
|
+
alt={content.reactLogo.value}
|
|
238
|
+
width={48}
|
|
239
|
+
height={48}
|
|
240
|
+
/>
|
|
241
|
+
<p className="opacity-70">{content.readTheDocs}</p>
|
|
242
|
+
</>
|
|
243
|
+
);
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
> String-Attribute (`alt`, `title`, `aria-label`, …) benötigen `.value`:
|
|
249
|
+
>
|
|
250
|
+
> ```jsx
|
|
251
|
+
> <img alt={c.reactLogo.value} />
|
|
252
|
+
> ```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## (Optional) Schritt 6: Sprachumschaltung (Client)
|
|
257
|
+
|
|
258
|
+
```tsx fileName="src/components/LocaleSwitcher.tsx"
|
|
259
|
+
import { Locales } from "intlayer";
|
|
260
|
+
import { useLocale } from "react-intlayer";
|
|
261
|
+
|
|
262
|
+
export function LocaleSwitcher() {
|
|
263
|
+
const { setLocale } = useLocale();
|
|
264
|
+
return (
|
|
265
|
+
<div className="flex gap-2">
|
|
266
|
+
<button onClick={() => setLocale(Locales.ENGLISH)}>Englisch</button>
|
|
267
|
+
<button onClick={() => setLocale(Locales.FRENCH)}>Französisch</button>
|
|
268
|
+
<button onClick={() => setLocale(Locales.SPANISH)}>Spanisch</button>
|
|
269
|
+
</div>
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## (Optional) Schritt 7: Lokalisierte Routenführung (SEO-freundliche URLs)
|
|
277
|
+
|
|
278
|
+
Sie haben **zwei gute Muster** mit TanStack Start. Wählen Sie eines aus.
|
|
279
|
+
|
|
280
|
+
Erstellen Sie einen dynamischen Segmentordner `src/routes/$locale/`, sodass Ihre URLs `/:locale/...` sind. Validieren Sie im `$locale`-Layout den `params.locale`, setzen Sie `<IntlayerProvider locale=...>` und rendern Sie ein `<Outlet />`. Dieser Ansatz ist unkompliziert, aber Sie werden den Rest Ihrer Routen unterhalb von `$locale` mounten, und Sie benötigen einen zusätzlichen nicht-präfixierten Baum, wenn Sie _nicht_ möchten, dass die Standardsprache mit einem Präfix versehen wird.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## (Optional) Schritt 8: URL beim Wechseln der Sprache aktualisieren
|
|
285
|
+
|
|
286
|
+
Mit Muster A (Basis-Pfad) bedeutet das Wechseln der Sprache, **zu einem anderen Basis-Pfad zu navigieren**:
|
|
287
|
+
|
|
288
|
+
```tsx fileName="src/components/LocaleSwitcherNavigate.tsx"
|
|
289
|
+
import { useRouter } from "@tanstack/react-router";
|
|
290
|
+
import { Locales, getLocalizedUrl } from "intlayer";
|
|
291
|
+
import { useLocale } from "react-intlayer";
|
|
292
|
+
|
|
293
|
+
export function LocaleSwitcherNavigate() {
|
|
294
|
+
const router = useRouter();
|
|
295
|
+
const { locale, setLocale } = useLocale();
|
|
296
|
+
|
|
297
|
+
const change = async (next: Locales) => {
|
|
298
|
+
if (next === locale) return;
|
|
299
|
+
const nextPath = getLocalizedUrl(
|
|
300
|
+
window.location.pathname + window.location.search,
|
|
301
|
+
next
|
|
302
|
+
);
|
|
303
|
+
await router.navigate({ to: nextPath }); // bewahrt die Historie
|
|
304
|
+
setLocale(next);
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
return (
|
|
308
|
+
<div className="flex gap-2">
|
|
309
|
+
<button onClick={() => change(Locales.ENGLISH)}>English</button>
|
|
310
|
+
<button onClick={() => change(Locales.FRENCH)}>Français</button>
|
|
311
|
+
<button onClick={() => change(Locales.SPANISH)}>Español</button>
|
|
312
|
+
</div>
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## (Optional) Schritt 9: `<html lang>` und `dir` (TanStack Start Dokument)
|
|
320
|
+
|
|
321
|
+
TanStack Start stellt ein **Document** (HTML-Wurzel-Shell) bereit, das Sie anpassen können. Setzen Sie `lang` und `dir` für Barrierefreiheit/SEO:
|
|
322
|
+
|
|
323
|
+
```tsx fileName="src/routes/__root.tsx" {4,15}
|
|
324
|
+
import { Outlet, createRootRoute } from "@tanstack/react-router";
|
|
325
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
326
|
+
import { getHTMLTextDir } from "intlayer";
|
|
327
|
+
|
|
328
|
+
function Document({
|
|
329
|
+
locale,
|
|
330
|
+
children,
|
|
331
|
+
}: {
|
|
332
|
+
locale: string;
|
|
333
|
+
children: React.ReactNode;
|
|
334
|
+
}) {
|
|
335
|
+
return (
|
|
336
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
337
|
+
<head>
|
|
338
|
+
<meta charSet="utf-8" />
|
|
339
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
340
|
+
{/* ... */}
|
|
341
|
+
</head>
|
|
342
|
+
<body>{children}</body>
|
|
343
|
+
</html>
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export const Route = createRootRoute({
|
|
348
|
+
component: () => (
|
|
349
|
+
<IntlayerProvider>
|
|
350
|
+
{/* Wenn Sie die Locale auf dem Server berechnen, übergeben Sie sie an Document; andernfalls korrigiert der Client dies nach der Hydrierung */}
|
|
351
|
+
<Document locale={document?.documentElement?.lang || "en"}>
|
|
352
|
+
<Outlet />
|
|
353
|
+
</Document>
|
|
354
|
+
</IntlayerProvider>
|
|
355
|
+
),
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Für eine clientseitige Korrektur können Sie auch Ihren kleinen Hook beibehalten:
|
|
360
|
+
|
|
361
|
+
```tsx fileName="src/hooks/useI18nHTMLAttributes.tsx"
|
|
362
|
+
import { useEffect } from "react";
|
|
363
|
+
import { useLocale } from "react-intlayer";
|
|
364
|
+
import { getHTMLTextDir } from "intlayer";
|
|
365
|
+
|
|
366
|
+
export const useI18nHTMLAttributes = () => {
|
|
367
|
+
const { locale } = useLocale();
|
|
368
|
+
useEffect(() => {
|
|
369
|
+
document.documentElement.lang = locale;
|
|
370
|
+
document.documentElement.dir = getHTMLTextDir(locale);
|
|
371
|
+
}, [locale]);
|
|
372
|
+
};
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## (Optional) Schritt 10: Lokalisierte Link-Komponente
|
|
378
|
+
|
|
379
|
+
TanStack Router stellt ein `<Link/>` bereit, aber falls Sie jemals einen einfachen `<a>`-Tag benötigen, der interne URLs automatisch mit einem Präfix versieht:
|
|
380
|
+
|
|
381
|
+
```tsx fileName="src/components/Link.tsx"
|
|
382
|
+
import { getLocalizedUrl } from "intlayer";
|
|
383
|
+
import {
|
|
384
|
+
forwardRef,
|
|
385
|
+
type AnchorHTMLAttributes,
|
|
386
|
+
type DetailedHTMLProps,
|
|
387
|
+
} from "react";
|
|
388
|
+
import { useLocale } from "react-intlayer";
|
|
389
|
+
|
|
390
|
+
export interface LinkProps
|
|
391
|
+
extends DetailedHTMLProps<
|
|
392
|
+
AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
393
|
+
HTMLAnchorElement
|
|
394
|
+
> {}
|
|
395
|
+
|
|
396
|
+
const isExternal = (href?: string) => /^https?:\/\//.test(href ?? "");
|
|
397
|
+
|
|
398
|
+
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
|
|
399
|
+
({ href, children, ...props }, ref) => {
|
|
400
|
+
const { locale } = useLocale();
|
|
401
|
+
const hrefI18n =
|
|
402
|
+
href && !isExternal(href) ? getLocalizedUrl(href, locale) : href;
|
|
403
|
+
return (
|
|
404
|
+
<a href={hrefI18n} ref={ref} {...props}>
|
|
405
|
+
{children}
|
|
406
|
+
</a>
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
);
|
|
410
|
+
Link.displayName = "Link";
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
> Wenn Sie Muster A (basepath) verwenden, löst TanStacks `<Link to="/about" />` bereits über `basepath` zu `/fr/about` auf, daher ist ein benutzerdefinierter Link optional.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## TypeScript
|
|
418
|
+
|
|
419
|
+
Fügen Sie die von Intlayer generierten Typen ein:
|
|
420
|
+
|
|
421
|
+
```json5 fileName="tsconfig.json"
|
|
422
|
+
{
|
|
423
|
+
"include": ["src", ".intlayer/**/*.ts"],
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Git
|
|
430
|
+
|
|
431
|
+
Ignorieren Sie die von Intlayer generierten Artefakte:
|
|
432
|
+
|
|
433
|
+
```gitignore
|
|
434
|
+
.intlayer
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## VS Code Erweiterung
|
|
440
|
+
|
|
441
|
+
- **Intlayer VS Code Erweiterung** → Autovervollständigung, Fehler, Inline-Vorschauen, Schnellaktionen.
|
|
442
|
+
Marketplace: `intlayer.intlayer-vs-code-extension`
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Weiterführende Themen
|
|
447
|
+
|
|
448
|
+
- Visueller Editor
|
|
449
|
+
- CMS-Modus
|
|
450
|
+
- Lokalerkennung am Edge / Adapter
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
## Dokumentationshistorie
|
|
455
|
+
|
|
456
|
+
| Version | Datum | Änderungen |
|
|
457
|
+
| ------- | ---------- | ------------------------------------ |
|
|
458
|
+
| 1.0.0 | 2025-08-11 | TanStack Start-Anpassung hinzugefügt |
|
|
@@ -279,7 +279,6 @@ Intlayer bietet viele Funktionen, die Ihnen helfen, Ihre Next.js-Anwendung zu in
|
|
|
279
279
|
- [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/next-intlayer/useIntlayer.md)
|
|
280
280
|
- [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/next-intlayer/useDictionary.md)
|
|
281
281
|
- [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/next-intlayer/useLocale.md)
|
|
282
|
-
- [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/next-intlayer/useIntlayerAsync.md)
|
|
283
282
|
|
|
284
283
|
## Dokumentationshistorie
|
|
285
284
|
|
|
@@ -274,7 +274,6 @@ Das Paket `react-intlayer` stellt ebenfalls einige Funktionen bereit, die Ihnen
|
|
|
274
274
|
- [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/react-intlayer/useIntlayer.md)
|
|
275
275
|
- [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/react-intlayer/useDictionary.md)
|
|
276
276
|
- [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/react-intlayer/useLocale.md)
|
|
277
|
-
- [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/de/packages/react-intlayer/useIntlayerAsync.md)
|
|
278
277
|
|
|
279
278
|
## Dokumentationshistorie
|
|
280
279
|
|
package/docs/en/CI_CD.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-05-20
|
|
3
|
-
updatedAt: 2025-
|
|
3
|
+
updatedAt: 2025-08-13
|
|
4
4
|
title: CI/CD Integration
|
|
5
5
|
description: Learn how to integrate Intlayer into your CI/CD pipeline for automated content management and deployment.
|
|
6
6
|
keywords:
|
|
@@ -109,58 +109,82 @@ Intlayer provides a CLI command to autofill and review dictionary content. This
|
|
|
109
109
|
|
|
110
110
|
```yaml fileName=".github/workflows/intlayer-translate.yml"
|
|
111
111
|
name: Intlayer Auto-Fill
|
|
112
|
+
# Trigger conditions for this workflow
|
|
112
113
|
on:
|
|
113
|
-
push:
|
|
114
|
-
branches: [ main ]
|
|
115
|
-
paths:
|
|
116
|
-
- 'src/**'
|
|
117
114
|
pull_request:
|
|
118
|
-
branches:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
branches:
|
|
116
|
+
- "main"
|
|
117
|
+
|
|
118
|
+
permissions:
|
|
119
|
+
contents: write
|
|
120
|
+
pull-requests: write
|
|
122
121
|
|
|
123
122
|
concurrency:
|
|
124
|
-
group:
|
|
123
|
+
group: "autofill-${{ github.ref }}"
|
|
125
124
|
cancel-in-progress: true
|
|
126
125
|
|
|
127
126
|
jobs:
|
|
128
127
|
autofill:
|
|
129
128
|
runs-on: ubuntu-latest
|
|
130
129
|
env:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
# OpenAI
|
|
131
|
+
AI_MODEL: openai
|
|
132
|
+
AI_PROVIDER: gpt-5-mini
|
|
133
|
+
AI_API_KEY: ${{ secrets.AI_API_KEY }}
|
|
134
134
|
|
|
135
135
|
steps:
|
|
136
|
+
# Step 1: Get the latest code from the repository
|
|
136
137
|
- name: ⬇️ Checkout repository
|
|
137
|
-
uses: actions/checkout@
|
|
138
|
+
uses: actions/checkout@v4
|
|
138
139
|
with:
|
|
139
|
-
persist-credentials: true
|
|
140
|
+
persist-credentials: true # Keep credentials for creating PRs
|
|
141
|
+
fetch-depth: 0 # Get full git history for diff analysis
|
|
140
142
|
|
|
143
|
+
# Step 2: Set up Node.js environment
|
|
141
144
|
- name: 🟢 Set up Node.js
|
|
142
|
-
uses: actions/setup-node@
|
|
145
|
+
uses: actions/setup-node@v4
|
|
143
146
|
with:
|
|
144
|
-
node-version: 20
|
|
147
|
+
node-version: 20 # Use Node.js 20 LTS for stability
|
|
145
148
|
|
|
149
|
+
# Step 3: Install project dependencies
|
|
146
150
|
- name: 📦 Install dependencies
|
|
147
|
-
run: npm
|
|
151
|
+
run: npm install
|
|
152
|
+
|
|
153
|
+
# Step 4: Install Intlayer CLI globally for translation management
|
|
154
|
+
- name: 📦 Install Intlayer
|
|
155
|
+
run: npm install -g intlayer-cli
|
|
148
156
|
|
|
157
|
+
# Step 5: Build the Intlayer project to generate translation files
|
|
149
158
|
- name: ⚙️ Build Intlayer project
|
|
150
159
|
run: npx intlayer build
|
|
151
160
|
|
|
161
|
+
# Step 6: Use AI to automatically fill missing translations
|
|
152
162
|
- name: 🤖 Auto-fill missing translations
|
|
153
|
-
run: npx intlayer fill --git-diff --mode fill
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
163
|
+
run: npx intlayer fill --git-diff --mode fill --provider $AI_PROVIDER --model $AI_MODEL --api-key $AI_API_KEY
|
|
164
|
+
|
|
165
|
+
# Step 7: Check if there are changes and commit them
|
|
166
|
+
- name: � Check for changes
|
|
167
|
+
id: check-changes
|
|
168
|
+
run: |
|
|
169
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
170
|
+
echo "has-changes=true" >> $GITHUB_OUTPUT
|
|
171
|
+
else
|
|
172
|
+
echo "has-changes=false" >> $GITHUB_OUTPUT
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# Step 8: Commit and push changes if any exist
|
|
176
|
+
- name: 📤 Commit and push changes
|
|
177
|
+
if: steps.check-changes.outputs.has-changes == 'true'
|
|
178
|
+
run: |
|
|
179
|
+
git config --local user.email "action@github.com"
|
|
180
|
+
git config --local user.name "GitHub Action"
|
|
181
|
+
git add .
|
|
182
|
+
git commit -m "chore: auto-fill missing translations [skip ci]"
|
|
183
|
+
git push origin HEAD:${{ github.head_ref }}
|
|
162
184
|
```
|
|
163
185
|
|
|
186
|
+
To set up the environment variables, go to GitHub → Settings → Secrets and variables → Actions and add the secret .
|
|
187
|
+
|
|
164
188
|
> Same as for Husky, in the case of a monorepo, you can use the `--base-dir` argument to sequentially treat each app.
|
|
165
189
|
|
|
166
190
|
> By default, the `--git-diff` argument filters dictionaries that include changes from base (default `origin/main`) to current branch (default: `HEAD`).
|