このページとあなたの好きなAIアシスタントを使ってドキュメントを要約します
バージョン履歴
- "初版"v9.5.102026/9/26
このページのコンテンツはAIを使用して翻訳されました。
英語の元のコンテンツの最新バージョンを見るこのドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンクドキュメントのMarkdownをクリップボードにコピー
2026年に Paraglide JS を使用して TanStack Start アプリケーションを国際化する方法
目次
Paraglide JS とは?
Paraglide JS(inlang 製)は、コンパイラベースの i18n ライブラリです。JSON オブジェクト内のキーを実行時に検索するランタイムを出荷する代わりに、各メッセージを型付き JavaScript 関数(m.about_title())にコンパイルします。未使用のメッセージはバンドラーによって削除(ツリーシェイキング)でき、キーのタイプミスはコンパイルエラーになります。
Paraglide は、公式の TanStack Router のサンプルで使用されている i18n アプローチであり、次の3つの要素を通じて TanStack Start と統合されます:
- メッセージとランタイムを
src/paraglideにコンパイルする Vite プラグイン - 各リクエストのロケールを解決するサーバーミドルウェア
- ローカライズされた URL(
/fr/about)をルートツリー(/about)にマッピングするルーターリライト($localeセグメントが不要になります)
本ガイドでは、これら3つの要素をすべて設定し、さらに Paraglide 単体では対応していない項目(lang と dir、言語切替スイッチャー、翻訳されたメタデータ、canonical、x-default 付き hreflang、Open Graph、JSON-LD、サイトマップ、robots.txt、事前レンダリング、ローカライズされた 404 ページ)についても網羅して解説します。
他のスタックをお探しですか? TanStack Start + use-intl ガイド、TanStack Start + Lingui ガイド、または TanStack Start + Intlayer ガイドをご覧ください。
2つのコンパイラベースのアプローチを比較したいですか? Intlayer は Paraglide より軽量か?をお読みください。
TanStack Start における Paraglide のベンチマーク結果
i18n ベンチマークでは、主要な各ライブラリを使用して同じ 10 ページ・10 言語の TanStack Start アプリを実行し、ブラウザが実際にダウンロードするサイズを測定しています。
動的な JSON 読み込み
実行時に翻訳を遅延読み込みします
スコープ付き JSON (ネームスペース)
ページごとの翻訳ネームスペース
I18n パフォーマンス ベンチマーク
この指標は何ですか?
国際化ライブラリバンドルの合計gzip圧縮サイズ。これには、ツリーシェイキングと縮小化(minification)後のプロバイダーとコンテンツ取得ロジックのみが含まれます。
なぜ重要なのか?
ライブラリのサイズが小さければ初期 JavaScript ペイロードが削減され、クライアント側でのダウンロードと実行が高速化されます।
表示形式
@inlang/paraglide-js@2.15.1 の主要数値(2026-09-26 測定、gzip):
テーブルをモーダルで開き、すべてのデータを明確に表示
| 構成 | ライブラリサイズ | ページごとの JS | 他ロケールの漏洩 | 他ページの漏洩 | ページ読み込み |
|---|---|---|---|---|---|
| i18n なし(ベースアプリ) | - | 111.0 KB | 0% | 0% | 15.7 ms |
| Paraglide JS | 1.8 KB | 125.1 KB | 49.7% | 0% | 22.1 ms |
react-intlayer | 4.5 KB | 126.8 KB | 0% | 0% | 14.8 ms |
use-intl | 75.9 KB | 128.7 KB | 0% | 0% | 17.4 ms |
| Lingui | 56.7 KB | 120.2 KB | 8.6% | 0% | 21.9 ms |
ポイント:
- ランタイムは非常に小さく、ページの漏洩はありません。 ランタイムは設定に応じて生成され、メッセージは使用される場所でのみインポートされます。
- ロケールの漏洩が発生します。 各メッセージ関数にはすべてのロケールが含まれているため、ページに配信される翻訳文字列の約半分は訪問者が使用しない言語のものになります。ロケールを追加するほど、この割合は大きくなります。
- ページ読み込み時間はグループ内で最も遅くなります。 これは、ロケールが React コンテキストから読み取られるのではなく、呼び出しごとに戦略を通じて解決されることが一因です。
完全なデータをご覧ください:TanStack Start ベンチマークレポート、およびベンチマークリポジトリ。
TanStack Start における機能比較
TanStack Start でよく使用される他のライブラリとの Paraglide JS の比較:
テーブルをモーダルで開き、すべてのデータを明確に表示
| 機能 | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| コンポーネント近傍の翻訳管理 | ✅ 同一場所に配置(Co-located) | ❌ 中央集権型 JSON | ❌ 1ロケールにつき1つの JSON ファイル | ⚠️ コンポーネント内のソーステキスト |
| TypeScript 統合 | ✅ 型の自動生成 | ✅ AppConfig 経由 | ✅ 型付きメッセージ関数 | ⚠️ マクロのみ |
| 未翻訳メッセージの検出 | ✅ 型エラーとビルド警告 | ⚠️ ランタイムフォールバック | ⚠️ ベースロケールにフォールバック | ⚠️ ソーステキストにフォールバック |
| リッチコンテンツ(JSX、Markdown) | ✅ 直接サポート | ⚠️ t.rich 経由のタグ | ⚠️ 文字列のみ | ✅ <Trans> 内の JSX |
| ローカライズされたルーティング | ✅ 組み込み | ❌ 手動の {-$locale} | ✅ urlPatterns + ルーターリライト | ❌ 手動の {-$locale} |
| リロードなしのロケール切り替え | ✅ 可能 | ✅ 可能 | ❌ ページ全体の再読み込み | ✅ 可能 |
| 複数形対応 | ✅ 列挙型ベース | ✅ ICU | ✅ バリアント | ✅ ICU |
| ICU MessageFormat | ✅ format: "icu" 経由 | ✅ ネイティブ | ⚠️ inlang プラグイン経由 | ✅ ネイティブ |
| コンテンツ形式 | ✅ .ts、.json、.md、.yaml など | ⚠️ .json | ⚠️ inlang JSON | ✅ PO、JSON、CSV |
| AI 翻訳 | ✅ 独自のプロバイダーとキーを使用 | ❌ 非対応 | ❌ 非対応 | ❌ 非対応 |
| ビジュアルエディター / CMS | ✅ ローカルエディター + オプションの CMS | ❌ 外部プラットフォーム | ⚠️ inlang エコシステムアプリ | ❌ 外部プラットフォーム |
| SEO ヘルパー(hreflang、サイトマップ) | ✅ 組み込み | ❌ 手動 | ⚠️ ローカライズ URL のみ、残りは手動 | ❌ 手動 |
| ランタイムサイズ(gzip、ベンチマーク) | 4.5 KB | 75.9 KB | 1.8 KB | 56.7 KB |
| 漏洩率、最適構成(ロケール / ページ) | 0% / 0% | 0% / 0% | 49.7% / 0% | 8.6% / 0% |
| CI での未翻訳検出 | ✅ npx intlayer test | ⚠️ 組み込みなし | ⚠️ 組み込みなし | ✅ lingui compile --strict |
ランタイムサイズと漏洩率の数値は TanStack Start ベンチマークに基づいています。漏洩率は各ライブラリの最適構成で測定されています。
他の TanStack Start ガイド:Lingui、use-intl、および Intlayer。
推奨される実践プラクティス
- サーバー側で、解決されたロケールから
<html>のlangとdirを設定します。 - すべての言語バージョンがインデックス可能になるよう、プレフィックス戦略(
/fr/about)を使用して 1ロケールにつき1つの URL を維持します。 - URL が信頼できる唯一の情報源(Source of Truth)となり、クローラーがリクエストしたページを確実に取得できるよう、ロケール戦略で
urlを最優先にします。 - 関数名にすっきりとマッピングされる、フラットで説明的なメッセージキー(
about_title)を使用します。 - 生成されたファイルでのマージ競合を避けるため、生成された
src/paraglideフォルダではなくmessages/*.jsonをコミットします。 - メタデータを翻訳し、すべてのページで
canonical、hreflang、およびx-defaultを宣言します。 - 多言語サイトマップと robots.txt を生成し、すべてのロケールを事前レンダリングします。
- クローラーがすべての言語を発見できるように、言語スイッチャーには本物のリンクを使用します。
国際化と SEO ガイドおよび hreflang ガイドをご覧ください。
TanStack Start アプリケーションで Paraglide JS をセットアップするステップバイステップガイド
作成するプロジェクト構造は以下の通りです:
コードをクリップボードにコピー
$locale フォルダが存在しないことに注目してください。ルーターリライトによって、ルートマッチングの前にプレフィックスが削除されます。
依存関係のインストール
TanStack Start プロジェクトから開始し、Paraglide を初期化します。初期化コマンドにより
project.inlang/settings.jsonと最初のmessages/en.jsonが作成され、パッケージがインストールされます。bashコードをコピーコードをクリップボードにコピー
- @inlang/paraglide-js: コンパイラおよびその Vite プラグイン。インストールするランタイムパッケージはありません。ランタイムはプロジェクト内に直接生成されます。
ロケールの設定
project.inlang/settings.jsonはロケールの唯一の情報源です。メッセージフォーマットプラグインは、ロケールごとに1つの JSON ファイルを読み込みます。project.inlang/settings.jsonコードをコピーコードをクリップボードにコピー
Vite プラグインと URL 戦略の設定
プラグインは変更のたびにメッセージをコンパイルします。TanStack Start では3つのオプションが重要です:
strategy: ロケールを読み取る場所の優先順位リスト。urlを先頭にすることで URL を信頼できる情報源にします。cookieとpreferredLanguageは、URL からロケールを決定できない場合にミドルウェアによって使用されます。urlPatterns: ロケールを URL にマッピングする方法。最初に一致したパターンが優先されるため、デフォルト以外のロケールを先に記述します。ここでは、デフォルトロケールにはプレフィックスを付けず(/about)、他のロケールにはプレフィックスを付けます(/fr/about)。outputStructure: "message-modules": メッセージごとに1つのモジュールを生成し、ページがインポートしていないメッセージをバンドラーが削除できるようにします。
vite.config.tsコードをコピーコードをクリップボードにコピー
生成されたフォルダを
.gitignoreに追加します。このフォルダはdevやbuild時に再生成されます:.gitignoreコードをコピーコードをクリップボードにコピー
翻訳ファイルの作成
各キーは
src/paraglide/messagesからエクスポートされる関数になります。フラットな snake_case のキーを使用すると、最もすっきりとした関数名になります。変数は{name}プレースホルダーを使用します。messages/en.jsonコードをコピーコードをクリップボードにコピー
messages/fr.jsonコードをコピーコードをクリップボードにコピー
複数形には inlang メッセージフォーマットのバリアント構文を使用します:
messages/en.jsonコードをコピーコードをクリップボードにコピー
サーバーミドルウェアの追加
ミドルウェアは設定した戦略に従って各リクエストのロケールを解決し、
AsyncLocalStorageスコープを通じてサーバーレンダリング全体でgetLocale()から利用できるようにします。これにより、異なる言語の同時リクエストを安全に処理できます。TanStack Start では、デフォルトのサーバーエントリーをラップします:
src/server.tsコードをコピーコードをクリップボードにコピー
ルーターでローカライズされた URL をリライト
TanStack Router の
rewriteオプションは、ルーターの境界で URL を変換します:- 入力(input):
/fr/aboutはルートマッチングの前に/aboutに非ローカライズ(de-localized)されるため、単一のabout.tsxルートですべての言語に対応できます。 - 出力(output): 生成されるすべての
href(リンク、リダイレクト、ナビゲーション)はアクティブなロケール用にローカライズされるため、フランス語のページでは<Link to="/about">が/fr/aboutとしてレンダリングされます。
src/router.tsxコードをコピーコードをクリップボードにコピー
リンクはリライトによってローカライズされるため、カスタムの
LocalizedLinkコンポーネントは不要です。通常通り TanStack Router のLinkを使用できます。- 入力(input):
ルートドキュメントの作成
getLocale()はサーバー上ではミドルウェアによって解決されたロケールを返し、ブラウザ内では URL からロケールを取得するため、サーバー HTML とハイドレーション後でlangとdirが完全に一致します。src/i18n/config.tsコードをコピーコードをクリップボードにコピー
src/routes/__root.tsxコードをコピーコードをクリップボードにコピー
ページで翻訳を利用する
メッセージは通常の関数です。
mをインポートし、関数を呼び出して、変数をオブジェクトとして渡します。変数を含め、すべてが型付けされています。src/routes/index.tsxコードをコピーコードをクリップボードにコピー
src/routes/about.tsxコードをコピーコードをクリップボードにコピー
メッセージ関数は明示的なロケールも受け取ることができます:
m.about_title({}, { locale: "fr" })。これは、メール送信など、リクエストの言語とは異なる言語をレンダリングするサーバーサイドコードで便利です。コンテンツの言語を切り替える
オプションクローラーがすべての言語を発見できるように、スイッチャーは
localizeHrefを使用したリンクとしてレンダリングします。setLocaleは選択内容を Cookie に保存し、新しい言語でページをリロードします。メッセージ関数は React の state をサブスクライブするのではなく呼び出しごとにロケールを読み取るため、ページ全体の再読み込みが Paraglide の想定された動作となります。src/components/LocaleSwitcher.tsxコードをコピーコードをクリップボードにコピー
メタデータの国際化
オプション各言語バージョンが個別に検索順位を獲得できるよう、すべてのページで以下を公開します:
- 翻訳された
<title>とdescription - 自身を指す canonical URL
- ロケールごとの
hreflang代替リンクおよびx-default - Open Graph(
og:locale、og:locale:alternate、og:url) inLanguageを含む JSON-LD
Paraglide の
localizeUrlはurlPatternsから代替 URL を構築するため、実際のルーティングと乖離することがありません:src/i18n/seo.tsコードをコピーコードをクリップボードにコピー
- 翻訳された
サイトマップの国際化
オプション多言語サイトマップはすべてのロケールの各 URL を一覧表示し、各エントリで
xhtml:linkを使用してそのすべての代替言語を宣言します:src/routes/sitemap[.]xml.tsコードをコピーコードをクリップボードにコピー
robots.txt の国際化
オプション非公開ルートはすべての言語に存在するため、
Disallowルールはローカライズされたすべてのパスをカバーする必要があります。スターターによって作成されたpublic/robots.txtがある場合は削除し、ルートから配信します:src/routes/robots[.]txt.tsコードをコピーコードをクリップボードにコピー
すべてのロケールを事前レンダリングする
オプションTanStack Start ですべての言語バージョンを事前レンダリングできるように、各ページのローカライズされたパスを列挙します。
localizeHrefはブラウザ依存のない生成コードであるためvite.config.ts内で実行できますが、初回コンパイル後にのみファイルが存在します。以下のように手動でパスを列挙することで、ビルド順序の問題を回避できます:vite.config.tsコードをコピーコードをクリップボードにコピー
スイッチャーが本物のリンクをレンダリングするため、
crawlLinks: trueにより列挙し忘れたページも自動的に検出されます。ローカライズされた 404 ページの処理
オプションリライトにより
/fr/does-not-existは/does-not-existとしてマッチングされますが、getLocale()は依然としてfrを返すため、ステップ7のルートnotFoundComponentはフランス語でレンダリングされます。キャッチオールルートを追加することで、深いパスでも確実に到達できるようにします。ページにnoindexを設定します(React 19 では<meta>が<head>に自動ホイスティングされます)。src/components/NotFound.tsxコードをコピーコードをクリップボードにコピー
src/routes/$.tsxコードをコピーコードをクリップボードにコピー
サーバー関数でロケールにアクセスする
オプションサーバー関数は Paraglide ミドルウェアのスコープ内で実行されるため、そこでも
getLocale()が正常に動作します:src/server/sendWelcomeEmail.tsコードをコピーコードをクリップボードにコピー
Intlayer との比較
オプションParaglide から Intlayer へのドロップインアダプターは存在しません。両者はビルド時にコンテンツをコンパイルし、ランタイムを最小限に抑えるという同じ思想に従っているためです。違いは、ブラウザに配信される内容とコンテンツの整理方法にあります:
- ロケール: Intlayer はロケールごとに動的辞書をロードします(ベンチマークでのロケール漏洩率は 0%)。一方、Paraglide の各メッセージ関数はすべてのロケールを保持します(49.7%)。
- コンテンツの整理: 各コンポーネントの隣に
.content.tsファイルを配置することも、中央ファイルで一括管理することも可能です。コンポーネント単位 vs 中央集権型 i18n をご覧ください。 - ロケール切り替え: コンテンツは React コンテキストから読み取られるため、ロケールの切り替え時にリロードなしで再レンダリングされます。
- 生成コード:
src内に何も生成されないため、コミット前に再生成する必要がありません。
Paraglide 以外のライブラリから移行する場合は、互換アダプターを使用することで、
use-intl、next-intl、react-i18next、react-intl、または Lingui の API を維持したままランタイムを切り替えることができます。Intlayer は Paraglide より軽量か? および Intlayer TanStack Start ガイドをご覧ください。
Intlayer を使用して翻訳を自動化する
オプションParaglide は翻訳のレンダリングを行いますが、翻訳の生成はサポートしていません。Intlayer は無料かつオープンソースであり、そのツール群は Paraglide プロジェクトでも活用できます:
- 独自の API キーとプロバイダーを使用して AI で翻訳します。自動入力および CLI をご覧ください。
- JSON 同期プラグインを使用して、JSON ファイルを信頼できる情報源として維持します。
- CI で不足している翻訳をテストします。翻訳のテストをご覧ください。
- スキャンコマンドを使用して、デプロイ済みサイトの
hreflang欠落、誤った canonical、ロケール漏洩をスキャンします。
よくある質問
堅実な選択肢の1つです。公式の TanStack Router サンプルで使用されており、ベンチマークで最も小さいランタイム(gzip で約 1.8 KB)を持ち、メッセージは完全に型付けされています。トレードオフとしては、すべてのメッセージ関数に全ロケールが含まれるため翻訳文字列の約半分が他言語の訪問者に漏洩すること、およびロケール切り替え時にページ全体がリロードされることが挙げられます。
不要です。ルーターの rewrite により、ルートマッチングの前にロケールプレフィックスが削除され、生成されたリンクにプレフィックスが再付与されるため、単一の about.tsx で /about、/fr/about、および /es/about に対応できます。
メッセージ関数は React の state をサブスクライブしておらず、呼び出された時点でロケールを読み取ります。そのため、setLocale はデフォルトでページをリロードし、新しい言語ですべてのメッセージが再レンダリングされるようにします。{ reload: false } を渡すこともできますが、その場合は自身でツリーを再レンダリングする必要があります。
コミットしないことをお勧めします。このフォルダは dev や build のたびに再生成されるため、コミットすると生成ファイルでのマージ競合の原因になります。代わりに messages/*.json と project.inlang/settings.json をコミットしてください。
ルートの head() 内で localizeUrl を使用してロケールごとに1つの絶対 URL を構築し、ベースロケールを指す x-default を追加します。ステップ10で再利用可能なヘルパーを提供しており、ステップ11では同じ代替リンクをサイトマップにも追加しています。
outputStructure: "message-modules" を使用すると、未使用のメッセージは削除されるため、他ページのコンテンツが漏洩することはありません。ただし、未使用のロケールはツリーシェイクされません。各メッセージ関数にはすべての翻訳が含まれているため、ベンチマークでは 49.7% のロケール漏洩が測定されています。
コメント
まだコメントはありません。最初のコメントを共有しましょう。
