@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: TanStack Start(React)でのIntlayerの使い始め
|
|
5
|
+
description: Intlayerを使ってTanStack Startアプリにi18nを追加する—コンポーネントレベルの辞書、ローカライズされたURL、SEOに適したメタデータ。
|
|
6
|
+
keywords:
|
|
7
|
+
- 国際化
|
|
8
|
+
- ドキュメント
|
|
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
|
+
# IntlayerとTanStack Start(React)で始める国際化(i18n)
|
|
22
|
+
|
|
23
|
+
## Intlayerとは?
|
|
24
|
+
|
|
25
|
+
**Intlayer**はReactアプリ向けのオープンソースのi18nツールキットです。以下を提供します:
|
|
26
|
+
|
|
27
|
+
- **TypeScriptの安全性を備えたコンポーネントローカル辞書**。
|
|
28
|
+
- **動的なメタデータとルート**(SEO対応)。
|
|
29
|
+
- **ランタイムでのロケール切り替え**(ロケール検出・保持のためのヘルパー付き)。
|
|
30
|
+
- **Viteプラグイン**(ビルド時の変換と開発者体験向上のため)。
|
|
31
|
+
|
|
32
|
+
このガイドでは、**TanStack Start**プロジェクト(内部でViteを使用し、ルーティング/SSRにTanStack Routerを使っている)にIntlayerを組み込む方法を説明します。
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## ステップ1:依存関係のインストール
|
|
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**:コア(設定、辞書、CLI/変換)。
|
|
53
|
+
- **react-intlayer**:React用の`<IntlayerProvider>`とフック。
|
|
54
|
+
- **vite-intlayer**:Viteプラグイン、加えてロケール検出/リダイレクト用のオプションミドルウェア(開発環境とSSR/プレビューで動作。プロダクションSSRでは`dependencies`に移動)。
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## ステップ2:Intlayerの設定
|
|
59
|
+
|
|
60
|
+
プロジェクトのルートに `intlayer.config.ts` を作成します:
|
|
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
|
+
// contentDir、contentFileExtensions、middlewareオプションなども調整可能です。
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default config;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
CommonJS/ESMのバリアントは、`cjs`/`mjs`を好む場合でも元のドキュメントと同じです。
|
|
77
|
+
|
|
78
|
+
> 完全な設定リファレンスは、Intlayerの設定ドキュメントをご覧ください。
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## ステップ3:Viteプラグイン(およびオプションのミドルウェア)を追加
|
|
83
|
+
|
|
84
|
+
**TanStack StartはViteを使用しているため**、`vite.config.ts` にIntlayerのプラグインを追加します:
|
|
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
|
+
// ロケール検出、クッキー、リダイレクトのためにオプションだが推奨:
|
|
96
|
+
intLayerMiddlewarePlugin(),
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> SSRをデプロイする場合は、`vite-intlayer`を`dependencies`に移動して、ミドルウェアが本番環境で動作するようにしてください。
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## ステップ4:コンテンツを宣言する
|
|
106
|
+
|
|
107
|
+
辞書ファイルは`./src`以下の任意の場所に配置します(デフォルトは`contentDir`)。例:
|
|
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
|
+
ja: "Vite ロゴ",
|
|
118
|
+
en: "Vite logo",
|
|
119
|
+
fr: "Logo Vite",
|
|
120
|
+
es: "Logo Vite",
|
|
121
|
+
}),
|
|
122
|
+
reactLogo: t({
|
|
123
|
+
ja: "React ロゴ",
|
|
124
|
+
en: "React logo",
|
|
125
|
+
fr: "Logo React",
|
|
126
|
+
es: "Logo React",
|
|
127
|
+
}),
|
|
128
|
+
title: t({
|
|
129
|
+
ja: "TanStack Start + React",
|
|
130
|
+
en: "TanStack Start + React",
|
|
131
|
+
fr: "TanStack Start + React",
|
|
132
|
+
es: "TanStack Start + React",
|
|
133
|
+
}),
|
|
134
|
+
count: t({
|
|
135
|
+
ja: "カウントは ",
|
|
136
|
+
en: "count is ",
|
|
137
|
+
fr: "le compte est ",
|
|
138
|
+
es: "el recuento es ",
|
|
139
|
+
}),
|
|
140
|
+
edit: t<ReactNode>({
|
|
141
|
+
ja: (
|
|
142
|
+
<>
|
|
143
|
+
<code>src/routes/index.tsx</code> を編集して保存し、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
|
+
en: "Click the logos to learn more",
|
|
165
|
+
fr: "Cliquez sur les logos pour en savoir plus",
|
|
166
|
+
es: "Haz clic en los logotipos para saber más",
|
|
167
|
+
ja: "ロゴをクリックして詳細を学ぶ",
|
|
168
|
+
}),
|
|
169
|
+
},
|
|
170
|
+
} satisfies Dictionary;
|
|
171
|
+
|
|
172
|
+
export default appContent;
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
JSON/ESM/CJS バリアントは、元のドキュメントと同様に動作します。
|
|
176
|
+
|
|
177
|
+
> TSX コンテンツですか?セットアップで必要な場合は `import React from "react"` を忘れないでください。
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## ステップ 5: TanStack Start を Intlayer でラップする
|
|
182
|
+
|
|
183
|
+
TanStack Start では、**ルートルート** がプロバイダーを設定する適切な場所です。
|
|
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
|
+
// トップレベルで辞書を使用する例:
|
|
195
|
+
const content = useIntlayer("app");
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<div>
|
|
199
|
+
<nav className="flex gap-3 p-3">
|
|
200
|
+
<RouterLink to="/">ホーム</RouterLink>
|
|
201
|
+
<RouterLink to="/about">アバウト</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
|
+
次に、ページでコンテンツを使用します:
|
|
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
|
+
> 文字列属性(`alt`、`title`、`aria-label`など)には `.value` が必要です:
|
|
248
|
+
>
|
|
249
|
+
> ```jsx
|
|
250
|
+
> <img alt={c.reactLogo.value} />
|
|
251
|
+
> ```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## (オプション)ステップ6:ロケール切り替え(クライアント)
|
|
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)}>English</button>
|
|
266
|
+
<button onClick={() => setLocale(Locales.FRENCH)}>Français</button>
|
|
267
|
+
<button onClick={() => setLocale(Locales.SPANISH)}>Español</button>
|
|
268
|
+
</div>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## (オプション)ステップ7:ローカライズされたルーティング(SEOに優しいURL)
|
|
276
|
+
|
|
277
|
+
TanStack Startには**2つの優れたパターン**があります。どちらかを選んでください。
|
|
278
|
+
|
|
279
|
+
動的セグメントフォルダ `src/routes/$locale/` を作成し、URLを `/:locale/...` にします。`$locale` レイアウト内で `params.locale` を検証し、`<IntlayerProvider locale=...>` を設定し、`<Outlet />` をレンダリングします。この方法はシンプルですが、残りのルートは `$locale` の下にマウントされ、デフォルトのロケールにプレフィックスを付けたくない場合は、プレフィックスなしの別のツリーが必要になります。
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## (オプション)ステップ8:ロケール切り替え時にURLを更新する
|
|
284
|
+
|
|
285
|
+
パターンA(ベースパス)では、ロケールを切り替えると**異なるベースパスへナビゲートする**ことを意味します:
|
|
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 }); // 履歴を保持
|
|
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
|
+
## (任意)ステップ9: `<html lang>` と `dir` の設定(TanStack Start Document)
|
|
319
|
+
|
|
320
|
+
TanStack Start はカスタマイズ可能な **Document**(ルートHTMLシェル)を提供します。アクセシビリティやSEOのために `lang` と `dir` を設定しましょう:
|
|
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
|
+
{/* サーバーでロケールを計算する場合はDocumentに渡してください。そうでなければクライアント側でハイドレーション後に修正されます */}
|
|
350
|
+
<Document locale={document?.documentElement?.lang || "en"}>
|
|
351
|
+
<Outlet />
|
|
352
|
+
</Document>
|
|
353
|
+
</IntlayerProvider>
|
|
354
|
+
),
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
クライアント側での修正のために、小さなフックを保持することもできます:
|
|
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
|
+
## (オプション)ステップ10:ローカライズされたLinkコンポーネント
|
|
377
|
+
|
|
378
|
+
TanStack Routerは`<Link/>`を提供していますが、内部URLに自動でプレフィックスを付けるプレーンな`<a>`タグが必要な場合:
|
|
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
|
+
> パターンA(basepath)を使用している場合、TanStackの`<Link to="/about" />`はすでに`basepath`を介して`/fr/about`に解決されるため、カスタムリンクはオプションです。
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## TypeScript
|
|
417
|
+
|
|
418
|
+
Intlayerの生成された型を含めてください:
|
|
419
|
+
|
|
420
|
+
```json5 fileName="tsconfig.json"
|
|
421
|
+
{
|
|
422
|
+
"include": ["src", ".intlayer/**/*.ts"],
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Git
|
|
429
|
+
|
|
430
|
+
Intlayerの生成されたアーティファクトを無視してください:
|
|
431
|
+
|
|
432
|
+
```gitignore
|
|
433
|
+
.intlayer
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## VS Code 拡張機能
|
|
439
|
+
|
|
440
|
+
- **Intlayer VS Code 拡張機能** → オートコンプリート、エラー表示、インラインプレビュー、クイックアクション。
|
|
441
|
+
マーケットプレイス: `intlayer.intlayer-vs-code-extension`
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## さらに進む
|
|
446
|
+
|
|
447
|
+
- ビジュアルエディター
|
|
448
|
+
- CMSモード
|
|
449
|
+
- エッジでのロケール検出 / アダプター
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## ドキュメント履歴
|
|
454
|
+
|
|
455
|
+
| バージョン | 日付 | 変更内容 |
|
|
456
|
+
| ---------- | ---------- | --------------------------- |
|
|
457
|
+
| 1.0.0 | 2025-08-11 | TanStack Start の適応を追加 |
|
|
@@ -279,7 +279,6 @@ Intlayerは、Next.jsアプリケーションの国際化を支援する多く
|
|
|
279
279
|
- [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/next-intlayer/useIntlayer.md)
|
|
280
280
|
- [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/next-intlayer/useDictionary.md)
|
|
281
281
|
- [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/next-intlayer/useLocale.md)
|
|
282
|
-
- [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/next-intlayer/useIntlayerAsync.md)
|
|
283
282
|
|
|
284
283
|
## ドキュメント履歴
|
|
285
284
|
|
|
@@ -280,7 +280,6 @@ Intlayerは、Reactアプリケーションの国際化を支援する多くの
|
|
|
280
280
|
- [`useIntlayer()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/react-intlayer/useIntlayer.md)
|
|
281
281
|
- [`useDictionary()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/react-intlayer/useDictionary.md)
|
|
282
282
|
- [`useLocale()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/react-intlayer/useLocale.md)
|
|
283
|
-
- [`useIntlayerAsync()`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ja/packages/react-intlayer/useIntlayerAsync.md)
|
|
284
283
|
|
|
285
284
|
## ドキュメント履歴
|
|
286
285
|
|
package/docs/ko/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:
|
|
@@ -23,7 +23,7 @@ Intlayer는 콘텐츠 선언 파일에 대한 번역을 자동으로 생성할
|
|
|
23
23
|
|
|
24
24
|
## CMS 사용하기
|
|
25
25
|
|
|
26
|
-
Intlayer를 사용하면 로컬에서는 단일 로케일만 선언하고 모든 번역은 CMS를 통해 원격으로 관리하는 워크플로우를 채택할 수 있습니다. 이를 통해 콘텐츠와 번역이 코드베이스와 완전히 분리되어 콘텐츠 편집자에게 더 많은 유연성을 제공하며, 변경
|
|
26
|
+
Intlayer를 사용하면 로컬에서는 단일 로케일만 선언하고 모든 번역은 CMS를 통해 원격으로 관리하는 워크플로우를 채택할 수 있습니다. 이를 통해 콘텐츠와 번역이 코드베이스와 완전히 분리되어 콘텐츠 편집자에게 더 많은 유연성을 제공하며, 핫 콘텐츠 리로딩이 가능해져(변경 사항 적용을 위해 애플리케이션을 다시 빌드할 필요 없음) 편리합니다.
|
|
27
27
|
|
|
28
28
|
### 예제 구성
|
|
29
29
|
|
|
@@ -37,7 +37,7 @@ const config: IntlayerConfig = {
|
|
|
37
37
|
defaultLocale: Locales.ENGLISH,
|
|
38
38
|
},
|
|
39
39
|
editor: {
|
|
40
|
-
dictionaryPriorityStrategy: "distant_first", // 원격 콘텐츠가
|
|
40
|
+
dictionaryPriorityStrategy: "distant_first", // 원격 콘텐츠가 우선순위를 가집니다
|
|
41
41
|
|
|
42
42
|
applicationURL: process.env.APPLICATION_URL, // CMS에서 사용하는 애플리케이션 URL
|
|
43
43
|
|
|
@@ -56,7 +56,7 @@ CMS에 대해 더 알아보려면 [공식 문서](https://github.com/aymericzip/
|
|
|
56
56
|
|
|
57
57
|
## Husky 사용하기
|
|
58
58
|
|
|
59
|
-
[Husky](https://typicode.github.io/husky/)를 사용하여 로컬 Git 워크플로우에 번역 생성
|
|
59
|
+
[Husky](https://typicode.github.io/husky/)를 사용하여 로컬 Git 워크플로우에 번역 생성 과정을 통합할 수 있습니다.
|
|
60
60
|
|
|
61
61
|
### 예제 구성
|
|
62
62
|
|
|
@@ -77,7 +77,7 @@ const config: IntlayerConfig = {
|
|
|
77
77
|
provider: "openai",
|
|
78
78
|
apiKey: process.env.OPENAI_API_KEY, // 자신의 API 키를 사용하세요
|
|
79
79
|
|
|
80
|
-
applicationContext: "This is a test application", // 일관된 번역 생성을
|
|
80
|
+
applicationContext: "This is a test application", // 일관된 번역 생성을 돕습니다
|
|
81
81
|
},
|
|
82
82
|
};
|
|
83
83
|
|
|
@@ -85,13 +85,13 @@ export default config;
|
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
```bash fileName=".husky/pre-push"
|
|
88
|
-
npx intlayer build # 사전이 최신 상태인지
|
|
89
|
-
npx intlayer fill --unpushed --mode fill # 누락된 내용만 채우며, 기존 내용을 업데이트하지
|
|
88
|
+
npx intlayer build # 사전이 최신 상태인지 확인합니다
|
|
89
|
+
npx intlayer fill --unpushed --mode fill # 누락된 내용만 채우며, 기존 내용을 업데이트하지 않습니다
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
> Intlayer CLI 명령어 및 사용법에 대한 자세한 내용은 [CLI 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_cli.md)를 참조하세요.
|
|
93
93
|
|
|
94
|
-
> 저장소에 여러 앱이 있고 각각 별도의 intlayer 인스턴스를 사용하는 경우,
|
|
94
|
+
> 저장소에 여러 앱이 있고 각각 별도의 intlayer 인스턴스를 사용하는 경우, `--base-dir` 인수를 다음과 같이 사용할 수 있습니다:
|
|
95
95
|
|
|
96
96
|
```bash fileName=".husky/pre-push"
|
|
97
97
|
# 앱 1
|
|
@@ -105,68 +105,94 @@ npx intlayer fill --base-dir ./app2 --unpushed --mode fill
|
|
|
105
105
|
|
|
106
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
|
|
|
143
|
+
# 2단계: Node.js 환경 설정
|
|
141
144
|
- name: 🟢 Node.js 설정
|
|
142
|
-
uses: actions/setup-node@
|
|
145
|
+
uses: actions/setup-node@v4
|
|
143
146
|
with:
|
|
144
|
-
node-version: 20
|
|
147
|
+
node-version: 20 # 안정성을 위해 Node.js 20 LTS 사용
|
|
145
148
|
|
|
149
|
+
# 3단계: 프로젝트 의존성 설치
|
|
146
150
|
- name: 📦 의존성 설치
|
|
147
|
-
run: npm
|
|
151
|
+
run: npm install
|
|
152
|
+
|
|
153
|
+
# 4단계: 번역 관리를 위해 Intlayer CLI 전역 설치
|
|
154
|
+
- name: 📦 Intlayer 설치
|
|
155
|
+
run: npm install -g intlayer-cli
|
|
148
156
|
|
|
157
|
+
# 5단계: 번역 파일 생성을 위해 Intlayer 프로젝트 빌드
|
|
149
158
|
- name: ⚙️ Intlayer 프로젝트 빌드
|
|
150
159
|
run: npx intlayer build
|
|
151
160
|
|
|
161
|
+
# 6단계: AI를 사용하여 누락된 번역 자동 채우기
|
|
152
162
|
- name: 🤖 누락된 번역 자동 채우기
|
|
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
|
+
# 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: 누락된 번역 자동 채우기 [skip ci]"
|
|
183
|
+
git push origin HEAD:${{ github.head_ref }}
|
|
162
184
|
```
|
|
163
185
|
|
|
186
|
+
환경 변수를 설정하려면 GitHub → 설정 → Secrets and variables → Actions로 이동하여 비밀을 추가하세요.
|
|
187
|
+
|
|
164
188
|
> Husky와 마찬가지로, 모노레포의 경우 `--base-dir` 인수를 사용하여 각 앱을 순차적으로 처리할 수 있습니다.
|
|
165
189
|
|
|
166
|
-
> 기본적으로 `--git-diff` 인수는 기본 브랜치(기본값 `origin/main`)에서 현재 브랜치(
|
|
190
|
+
> 기본적으로 `--git-diff` 인수는 기본 브랜치(기본값 `origin/main`)에서 현재 브랜치(기본값: `HEAD`)로 변경된 사전을 필터링합니다.
|
|
167
191
|
|
|
168
192
|
> Intlayer CLI 명령어 및 사용법에 대한 자세한 내용은 [CLI 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_cli.md)를 참조하세요.
|
|
169
193
|
|
|
170
194
|
## 문서 이력
|
|
171
195
|
|
|
172
|
-
|
|
196
|
+
| 버전 | 날짜 | 변경 사항 |
|
|
197
|
+
| ------ | ---------- | --------- |
|
|
198
|
+
| 5.5.10 | 2025-06-29 | 초기 기록 |
|