@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,457 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2025-08-11
|
|
3
|
+
updatedAt: 2025-08-11
|
|
4
|
+
title: Iniziare con Intlayer in TanStack Start (React)
|
|
5
|
+
description: Aggiungi l'internazionalizzazione alla tua app TanStack Start usando Intlayer—dizionari a livello di componente, URL localizzati e metadati ottimizzati per SEO.
|
|
6
|
+
keywords:
|
|
7
|
+
- Internazionalizzazione
|
|
8
|
+
- Documentazione
|
|
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
|
+
# Iniziare con l'internazionalizzazione (i18n) usando Intlayer e TanStack Start (React)
|
|
22
|
+
|
|
23
|
+
## Cos'è Intlayer?
|
|
24
|
+
|
|
25
|
+
**Intlayer** è un toolkit open-source per l'internazionalizzazione (i18n) di app React. Ti offre:
|
|
26
|
+
|
|
27
|
+
- **Dizionari locali al componente** con sicurezza TypeScript.
|
|
28
|
+
- **Metadati e rotte dinamiche** (pronte per SEO).
|
|
29
|
+
- **Cambio della lingua a runtime** (e helper per rilevare/persistere le lingue).
|
|
30
|
+
- **Plugin Vite** per trasformazioni in fase di build + esperienza di sviluppo (DX).
|
|
31
|
+
|
|
32
|
+
Questa guida mostra come integrare Intlayer in un progetto **TanStack Start** (che utilizza Vite sotto il cofano e TanStack Router per il routing/SSR).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Passo 1: Installare le dipendenze
|
|
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**: core (configurazione, dizionari, CLI/trasformazioni).
|
|
53
|
+
- **react-intlayer**: `<IntlayerProvider>` + hook per React.
|
|
54
|
+
- **vite-intlayer**: plugin Vite, più middleware opzionale per il rilevamento/reindirizzamento della lingua (funziona in dev e SSR/preview; spostare in `dependencies` per SSR in produzione).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Passo 2: Configurare Intlayer
|
|
59
|
+
|
|
60
|
+
Crea `intlayer.config.ts` nella root del tuo progetto:
|
|
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
|
+
// Puoi anche modificare: contentDir, contentFileExtensions, opzioni del middleware, ecc.
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default config;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Le varianti CommonJS/ESM sono identiche al tuo documento originale se preferisci `cjs`/`mjs`.
|
|
77
|
+
|
|
78
|
+
> Riferimento completo alla configurazione: vedi la documentazione di configurazione di Intlayer.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Passo 3: Aggiungere il Plugin Vite (e middleware opzionale)
|
|
83
|
+
|
|
84
|
+
**TanStack Start usa Vite**, quindi aggiungi il/i plugin di Intlayer al tuo `vite.config.ts`:
|
|
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
|
+
// Opzionale ma consigliato per il rilevamento della lingua, cookie e reindirizzamenti:
|
|
96
|
+
intLayerMiddlewarePlugin(),
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> Se distribuisci SSR, sposta `vite-intlayer` nelle `dependencies` affinché il middleware funzioni in produzione.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Passo 4: Dichiara il tuo contenuto
|
|
106
|
+
|
|
107
|
+
Posiziona i tuoi dizionari ovunque sotto `./src` (default `contentDir`). Esempio:
|
|
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
|
+
it: "Logo Vite",
|
|
118
|
+
en: "Vite logo",
|
|
119
|
+
fr: "Logo Vite",
|
|
120
|
+
es: "Logo Vite",
|
|
121
|
+
}),
|
|
122
|
+
reactLogo: t({
|
|
123
|
+
it: "Logo React",
|
|
124
|
+
en: "React logo",
|
|
125
|
+
fr: "Logo React",
|
|
126
|
+
es: "Logo React",
|
|
127
|
+
}),
|
|
128
|
+
title: t({
|
|
129
|
+
it: "TanStack Start + React",
|
|
130
|
+
en: "TanStack Start + React",
|
|
131
|
+
fr: "TanStack Start + React",
|
|
132
|
+
es: "TanStack Start + React",
|
|
133
|
+
}),
|
|
134
|
+
count: t({
|
|
135
|
+
it: "il conteggio è ",
|
|
136
|
+
en: "count is ",
|
|
137
|
+
fr: "le compte est ",
|
|
138
|
+
es: "el recuento es ",
|
|
139
|
+
}),
|
|
140
|
+
edit: t<ReactNode>({
|
|
141
|
+
it: (
|
|
142
|
+
<>
|
|
143
|
+
Modifica <code>src/routes/index.tsx</code> e salva per testare HMR
|
|
144
|
+
</>
|
|
145
|
+
),
|
|
146
|
+
en: (
|
|
147
|
+
<>
|
|
148
|
+
Edit <code>src/routes/index.tsx</code> and save to test HMR
|
|
149
|
+
</>
|
|
150
|
+
),
|
|
151
|
+
fr: (
|
|
152
|
+
<>
|
|
153
|
+
Éditez <code>src/routes/index.tsx</code> et enregistrez pour tester
|
|
154
|
+
HMR
|
|
155
|
+
</>
|
|
156
|
+
),
|
|
157
|
+
es: (
|
|
158
|
+
<>
|
|
159
|
+
Edita <code>src/routes/index.tsx</code> y guarda para probar HMR
|
|
160
|
+
</>
|
|
161
|
+
),
|
|
162
|
+
}),
|
|
163
|
+
readTheDocs: t({
|
|
164
|
+
it: "Clicca sui loghi per saperne di più",
|
|
165
|
+
en: "Click the logos to learn more",
|
|
166
|
+
fr: "Cliquez sur les logos pour en savoir plus",
|
|
167
|
+
es: "Haz clic en los logotipos para saber más",
|
|
168
|
+
}),
|
|
169
|
+
},
|
|
170
|
+
} satisfies Dictionary;
|
|
171
|
+
|
|
172
|
+
export default appContent;
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Le varianti JSON/ESM/CJS funzionano allo stesso modo del tuo documento originale.
|
|
176
|
+
|
|
177
|
+
> Contenuto TSX? Non dimenticare `import React from "react"` se la tua configurazione lo richiede.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Passo 5: Avvolgi TanStack Start con Intlayer
|
|
182
|
+
|
|
183
|
+
Con TanStack Start, la tua **root route** è il posto giusto per impostare i provider.
|
|
184
|
+
|
|
185
|
+
```tsx fileName="src/routes/__root.tsx"
|
|
186
|
+
import {
|
|
187
|
+
Outlet,
|
|
188
|
+
createRootRoute,
|
|
189
|
+
Link as RouterLink,
|
|
190
|
+
} from "@tanstack/react-router";
|
|
191
|
+
import { IntlayerProvider, useIntlayer } from "react-intlayer";
|
|
192
|
+
|
|
193
|
+
function AppShell() {
|
|
194
|
+
// Esempio di utilizzo di un dizionario a livello superiore:
|
|
195
|
+
const content = useIntlayer("app");
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<div>
|
|
199
|
+
<nav className="flex gap-3 p-3">
|
|
200
|
+
<RouterLink to="/">Home</RouterLink>
|
|
201
|
+
<RouterLink to="/about">Informazioni</RouterLink>
|
|
202
|
+
</nav>
|
|
203
|
+
<main className="p-6">
|
|
204
|
+
<h1>{content.title}</h1>
|
|
205
|
+
<Outlet />
|
|
206
|
+
</main>
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export const Route = createRootRoute({
|
|
212
|
+
component: () => (
|
|
213
|
+
<IntlayerProvider>
|
|
214
|
+
<AppShell />
|
|
215
|
+
</IntlayerProvider>
|
|
216
|
+
),
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Quindi usa i tuoi contenuti nelle pagine:
|
|
221
|
+
|
|
222
|
+
```tsx fileName="src/routes/index.tsx"
|
|
223
|
+
import { createFileRoute } from "@tanstack/react-router";
|
|
224
|
+
import { useIntlayer } from "react-intlayer";
|
|
225
|
+
import reactLogo from "../assets/react.svg";
|
|
226
|
+
|
|
227
|
+
export const Route = createFileRoute("/")({
|
|
228
|
+
component: () => {
|
|
229
|
+
const content = useIntlayer("app");
|
|
230
|
+
return (
|
|
231
|
+
<>
|
|
232
|
+
<button>{content.count}0</button>
|
|
233
|
+
<p>{content.edit}</p>
|
|
234
|
+
<img
|
|
235
|
+
src={reactLogo}
|
|
236
|
+
alt={content.reactLogo.value}
|
|
237
|
+
width={48}
|
|
238
|
+
height={48}
|
|
239
|
+
/>
|
|
240
|
+
<p className="opacity-70">{content.readTheDocs}</p>
|
|
241
|
+
</>
|
|
242
|
+
);
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
> Gli attributi stringa (`alt`, `title`, `aria-label`, …) necessitano di `.value`:
|
|
248
|
+
>
|
|
249
|
+
> ```jsx
|
|
250
|
+
> <img alt={c.reactLogo.value} />
|
|
251
|
+
> ```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## (Opzionale) Passo 6: Cambio della lingua (Client)
|
|
256
|
+
|
|
257
|
+
```tsx fileName="src/components/LocaleSwitcher.tsx"
|
|
258
|
+
import { Locales } from "intlayer";
|
|
259
|
+
import { useLocale } from "react-intlayer";
|
|
260
|
+
|
|
261
|
+
export function LocaleSwitcher() {
|
|
262
|
+
const { setLocale } = useLocale();
|
|
263
|
+
return (
|
|
264
|
+
<div className="flex gap-2">
|
|
265
|
+
<button onClick={() => setLocale(Locales.ENGLISH)}>Inglese</button>
|
|
266
|
+
<button onClick={() => setLocale(Locales.FRENCH)}>Francese</button>
|
|
267
|
+
<button onClick={() => setLocale(Locales.SPANISH)}>Spagnolo</button>
|
|
268
|
+
</div>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## (Opzionale) Passo 7: Routing Localizzato (URL SEO-friendly)
|
|
276
|
+
|
|
277
|
+
Hai **due buoni modelli** con TanStack Start. Scegline uno.
|
|
278
|
+
|
|
279
|
+
Crea una cartella segmento dinamico `src/routes/$locale/` così i tuoi URL saranno `/:locale/...`. Nel layout `$locale`, valida `params.locale`, imposta `<IntlayerProvider locale=...>`, e renderizza un `<Outlet />`. Questo approccio è semplice, ma monterai il resto delle tue rotte sotto `$locale`, e avrai bisogno di un albero extra senza prefisso se _non_ vuoi il prefisso della locale di default.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## (Opzionale) Passo 8: Aggiornare l'URL quando si cambia lingua
|
|
284
|
+
|
|
285
|
+
Con il Pattern A (basepath), cambiare lingua significa **navigare verso un basepath differente**:
|
|
286
|
+
|
|
287
|
+
```tsx fileName="src/components/LocaleSwitcherNavigate.tsx"
|
|
288
|
+
import { useRouter } from "@tanstack/react-router";
|
|
289
|
+
import { Locales, getLocalizedUrl } from "intlayer";
|
|
290
|
+
import { useLocale } from "react-intlayer";
|
|
291
|
+
|
|
292
|
+
export function LocaleSwitcherNavigate() {
|
|
293
|
+
const router = useRouter();
|
|
294
|
+
const { locale, setLocale } = useLocale();
|
|
295
|
+
|
|
296
|
+
const change = async (next: Locales) => {
|
|
297
|
+
if (next === locale) return;
|
|
298
|
+
const nextPath = getLocalizedUrl(
|
|
299
|
+
window.location.pathname + window.location.search,
|
|
300
|
+
next
|
|
301
|
+
);
|
|
302
|
+
await router.navigate({ to: nextPath }); // preserva la cronologia
|
|
303
|
+
setLocale(next);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
return (
|
|
307
|
+
<div className="flex gap-2">
|
|
308
|
+
<button onClick={() => change(Locales.ENGLISH)}>English</button>
|
|
309
|
+
<button onClick={() => change(Locales.FRENCH)}>Français</button>
|
|
310
|
+
<button onClick={() => change(Locales.SPANISH)}>Español</button>
|
|
311
|
+
</div>
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## (Opzionale) Passo 9: `<html lang>` e `dir` (TanStack Start Document)
|
|
319
|
+
|
|
320
|
+
TanStack Start espone un **Document** (shell HTML radice) che puoi personalizzare. Imposta `lang` e `dir` per accessibilità/SEO:
|
|
321
|
+
|
|
322
|
+
```tsx fileName="src/routes/__root.tsx" {4,15}
|
|
323
|
+
import { Outlet, createRootRoute } from "@tanstack/react-router";
|
|
324
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
325
|
+
import { getHTMLTextDir } from "intlayer";
|
|
326
|
+
|
|
327
|
+
function Document({
|
|
328
|
+
locale,
|
|
329
|
+
children,
|
|
330
|
+
}: {
|
|
331
|
+
locale: string;
|
|
332
|
+
children: React.ReactNode;
|
|
333
|
+
}) {
|
|
334
|
+
return (
|
|
335
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
336
|
+
<head>
|
|
337
|
+
<meta charSet="utf-8" />
|
|
338
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
339
|
+
{/* ... */}
|
|
340
|
+
</head>
|
|
341
|
+
<body>{children}</body>
|
|
342
|
+
</html>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export const Route = createRootRoute({
|
|
347
|
+
component: () => (
|
|
348
|
+
<IntlayerProvider>
|
|
349
|
+
{/* Se calcoli la locale sul server, passala a Document; altrimenti il client correggerà dopo l'idratazione */}
|
|
350
|
+
<Document locale={document?.documentElement?.lang || "en"}>
|
|
351
|
+
<Outlet />
|
|
352
|
+
</Document>
|
|
353
|
+
</IntlayerProvider>
|
|
354
|
+
),
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Per la correzione lato client, puoi anche mantenere il tuo piccolo hook:
|
|
359
|
+
|
|
360
|
+
```tsx fileName="src/hooks/useI18nHTMLAttributes.tsx"
|
|
361
|
+
import { useEffect } from "react";
|
|
362
|
+
import { useLocale } from "react-intlayer";
|
|
363
|
+
import { getHTMLTextDir } from "intlayer";
|
|
364
|
+
|
|
365
|
+
export const useI18nHTMLAttributes = () => {
|
|
366
|
+
const { locale } = useLocale();
|
|
367
|
+
useEffect(() => {
|
|
368
|
+
document.documentElement.lang = locale;
|
|
369
|
+
document.documentElement.dir = getHTMLTextDir(locale);
|
|
370
|
+
}, [locale]);
|
|
371
|
+
};
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## (Opzionale) Passo 10: Componente Link localizzato
|
|
377
|
+
|
|
378
|
+
TanStack Router fornisce un `<Link/>`, ma se mai avessi bisogno di un semplice `<a>` che aggiunge automaticamente il prefisso alle URL interne:
|
|
379
|
+
|
|
380
|
+
```tsx fileName="src/components/Link.tsx"
|
|
381
|
+
import { getLocalizedUrl } from "intlayer";
|
|
382
|
+
import {
|
|
383
|
+
forwardRef,
|
|
384
|
+
type AnchorHTMLAttributes,
|
|
385
|
+
type DetailedHTMLProps,
|
|
386
|
+
} from "react";
|
|
387
|
+
import { useLocale } from "react-intlayer";
|
|
388
|
+
|
|
389
|
+
export interface LinkProps
|
|
390
|
+
extends DetailedHTMLProps<
|
|
391
|
+
AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
392
|
+
HTMLAnchorElement
|
|
393
|
+
> {}
|
|
394
|
+
|
|
395
|
+
const isExternal = (href?: string) => /^https?:\/\//.test(href ?? "");
|
|
396
|
+
|
|
397
|
+
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
|
|
398
|
+
({ href, children, ...props }, ref) => {
|
|
399
|
+
const { locale } = useLocale();
|
|
400
|
+
const hrefI18n =
|
|
401
|
+
href && !isExternal(href) ? getLocalizedUrl(href, locale) : href;
|
|
402
|
+
return (
|
|
403
|
+
<a href={hrefI18n} ref={ref} {...props}>
|
|
404
|
+
{children}
|
|
405
|
+
</a>
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
Link.displayName = "Link";
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
> Se usi il Pattern A (basepath), il `<Link to="/about" />` di TanStack risolve già in `/fr/about` tramite `basepath`, quindi un link personalizzato è opzionale.
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## TypeScript
|
|
417
|
+
|
|
418
|
+
Includi i tipi generati da Intlayer:
|
|
419
|
+
|
|
420
|
+
```json5 fileName="tsconfig.json"
|
|
421
|
+
{
|
|
422
|
+
"include": ["src", ".intlayer/**/*.ts"],
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Git
|
|
429
|
+
|
|
430
|
+
Ignora gli artefatti generati da Intlayer:
|
|
431
|
+
|
|
432
|
+
```gitignore
|
|
433
|
+
.intlayer
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Estensione VS Code
|
|
439
|
+
|
|
440
|
+
- **Estensione Intlayer per VS Code** → completamento automatico, errori, anteprime inline, azioni rapide.
|
|
441
|
+
Marketplace: `intlayer.intlayer-vs-code-extension`
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## Approfondimenti
|
|
446
|
+
|
|
447
|
+
- Editor Visuale
|
|
448
|
+
- Modalità CMS
|
|
449
|
+
- Rilevamento della lingua al confine / adattatori
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Cronologia Documentazione
|
|
454
|
+
|
|
455
|
+
| Versione | Data | Modifiche |
|
|
456
|
+
| -------- | ---------- | ------------------------------------- |
|
|
457
|
+
| 1.0.0 | 2025-08-11 | Aggiunta l'adattamento TanStack Start |
|
|
@@ -279,7 +279,6 @@ Il pacchetto `next-intlayer` fornisce anche alcune funzioni per aiutarti a inter
|
|
|
279
279
|
- [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useIntlayer.md)
|
|
280
280
|
- [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useDictionary.md)
|
|
281
281
|
- [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useLocale.md)
|
|
282
|
-
- [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/next-intlayer/useIntlayerAsync.md)
|
|
283
282
|
|
|
284
283
|
## Cronologia della documentazione
|
|
285
284
|
|
|
@@ -274,7 +274,6 @@ Il pacchetto `react-intlayer` fornisce anche alcune funzioni per aiutarti a inte
|
|
|
274
274
|
- [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useIntlayer.md)
|
|
275
275
|
- [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useDictionary.md)
|
|
276
276
|
- [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useLocale.md)
|
|
277
|
-
- [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/packages/react-intlayer/useIntlayerAsync.md)
|
|
278
277
|
|
|
279
278
|
## Cronologia della documentazione
|
|
280
279
|
|
package/docs/ja/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 統合
|
|
5
5
|
description: Intlayer を CI/CD パイプラインに統合して、自動化されたコンテンツ管理とデプロイメントを実現する方法を学びます。
|
|
6
6
|
keywords:
|
|
@@ -19,11 +19,11 @@ slugs:
|
|
|
19
19
|
|
|
20
20
|
# CI/CD パイプラインでの翻訳の自動生成
|
|
21
21
|
|
|
22
|
-
Intlayer
|
|
22
|
+
Intlayer は、コンテンツ宣言ファイルの翻訳を自動生成することを可能にします。ワークフローに応じて、これを実現する複数の方法があります。
|
|
23
23
|
|
|
24
24
|
## CMS の利用
|
|
25
25
|
|
|
26
|
-
Intlayer
|
|
26
|
+
Intlayer を使用すると、ローカルでは単一のロケールのみを宣言し、すべての翻訳は CMS を通じてリモートで管理するワークフローを採用できます。これにより、コンテンツと翻訳がコードベースから完全に切り離され、コンテンツ編集者にとってより柔軟性が提供され、ホットコンテンツリロード(変更を適用するためにアプリケーションを再ビルドする必要なし)が可能になります。
|
|
27
27
|
|
|
28
28
|
### 設定例
|
|
29
29
|
|
|
@@ -54,7 +54,7 @@ export default config;
|
|
|
54
54
|
|
|
55
55
|
CMSの詳細については、[公式ドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/intlayer_CMS.md)を参照してください。
|
|
56
56
|
|
|
57
|
-
## Husky
|
|
57
|
+
## Huskyの使用
|
|
58
58
|
|
|
59
59
|
[Husky](https://typicode.github.io/husky/)を使用して、ローカルのGitワークフローに翻訳生成を統合できます。
|
|
60
60
|
|
|
@@ -77,7 +77,7 @@ const config: IntlayerConfig = {
|
|
|
77
77
|
provider: "openai",
|
|
78
78
|
apiKey: process.env.OPENAI_API_KEY, // ご自身のAPIキーを使用してください
|
|
79
79
|
|
|
80
|
-
applicationContext: "
|
|
80
|
+
applicationContext: "This is a test application", // 一貫した翻訳生成を支援します
|
|
81
81
|
},
|
|
82
82
|
};
|
|
83
83
|
|
|
@@ -89,7 +89,7 @@ npx intlayer build # 辞書が最新であることを
|
|
|
89
89
|
npx intlayer fill --unpushed --mode fill # 欠落しているコンテンツのみを埋め、既存のものは更新しません
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
> Intlayer
|
|
92
|
+
> Intlayer CLIコマンドとその使用方法の詳細については、[CLIドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/intlayer_cli.md)を参照してください。
|
|
93
93
|
|
|
94
94
|
> リポジトリ内に複数のアプリがあり、それぞれ別のintlayerインスタンスを使用している場合は、次のように`--base-dir`引数を使用できます。
|
|
95
95
|
|
|
@@ -103,70 +103,96 @@ npx intlayer build --base-dir ./app2
|
|
|
103
103
|
npx intlayer fill --base-dir ./app2 --unpushed --mode fill
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
## GitHub Actions
|
|
106
|
+
## GitHub Actionsの使用
|
|
107
107
|
|
|
108
|
-
Intlayer
|
|
108
|
+
Intlayerは辞書コンテンツの自動入力およびレビューを行うCLIコマンドを提供しています。これはGitHub Actionsを使用してCI/CDワークフローに統合することができます。
|
|
109
109
|
|
|
110
110
|
```yaml fileName=".github/workflows/intlayer-translate.yml"
|
|
111
111
|
name: Intlayer 自動入力
|
|
112
|
+
# このワークフローのトリガー条件
|
|
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
|
+
# ステップ1: リポジトリから最新コードを取得
|
|
136
137
|
- name: ⬇️ リポジトリをチェックアウト
|
|
137
|
-
uses: actions/checkout@
|
|
138
|
+
uses: actions/checkout@v4
|
|
138
139
|
with:
|
|
139
|
-
persist-credentials: true
|
|
140
|
+
persist-credentials: true # PR作成のための認証情報を保持
|
|
141
|
+
fetch-depth: 0 # 差分解析のために完全なGit履歴を取得
|
|
140
142
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
# ステップ 2: Node.js環境のセットアップ
|
|
144
|
+
- name: 🟢 Node.jsをセットアップ
|
|
145
|
+
uses: actions/setup-node@v4
|
|
143
146
|
with:
|
|
144
|
-
node-version: 20
|
|
147
|
+
node-version: 20 # 安定性のためNode.js 20 LTSを使用
|
|
145
148
|
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
# ステップ 3: プロジェクト依存関係のインストール
|
|
150
|
+
- name: 📦 依存関係をインストール
|
|
151
|
+
run: npm install
|
|
148
152
|
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
# ステップ 4: 翻訳管理のためにIntlayer CLIをグローバルインストール
|
|
154
|
+
- name: 📦 Intlayerをインストール
|
|
155
|
+
run: npm install -g intlayer-cli
|
|
151
156
|
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
# ステップ 5: 翻訳ファイルを生成するためにIntlayerプロジェクトをビルド
|
|
158
|
+
- name: ⚙️ Intlayerプロジェクトをビルド
|
|
159
|
+
run: npx intlayer build
|
|
154
160
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
# ステップ 6: AIを使って不足している翻訳を自動で埋める
|
|
162
|
+
- name: 🤖 欠落している翻訳を自動入力
|
|
163
|
+
run: npx intlayer fill --git-diff --mode fill --provider $AI_PROVIDER --model $AI_MODEL --api-key $AI_API_KEY
|
|
164
|
+
|
|
165
|
+
# ステップ7: 変更があるか確認し、あればコミットする
|
|
166
|
+
- name: � 変更を確認
|
|
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
|
+
# ステップ8: 変更があればコミットしてプッシュする
|
|
176
|
+
- name: 📤 変更をコミットしてプッシュ
|
|
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
|
|
|
164
|
-
|
|
186
|
+
環境変数を設定するには、GitHub → 設定 → Secrets and variables → Actions に移動し、シークレット(API_KEY)を追加してください。
|
|
187
|
+
|
|
188
|
+
> Huskyの場合と同様に、モノレポの場合は `--base-dir` 引数を使用して各アプリを順番に処理できます。
|
|
165
189
|
|
|
166
190
|
> デフォルトでは、`--git-diff` 引数はベース(デフォルトは `origin/main`)から現在のブランチ(デフォルトは `HEAD`)への変更を含む辞書をフィルタリングします。
|
|
167
191
|
|
|
168
|
-
> Intlayer CLI
|
|
192
|
+
> Intlayer CLIコマンドとその使用方法の詳細については、[CLIドキュメント](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/intlayer_cli.md)を参照してください。
|
|
169
193
|
|
|
170
194
|
## ドキュメント履歴
|
|
171
195
|
|
|
172
|
-
|
|
196
|
+
| バージョン | 日付 | 変更内容 |
|
|
197
|
+
| ---------- | ---------- | ------------ |
|
|
198
|
+
| 5.5.10 | 2025-06-29 | 履歴の初期化 |
|