このページとあなたの好きなAIアシスタントを使ってドキュメントを要約します
バージョン履歴
- "初版"v9.5.102026/9/26
このページのコンテンツはAIを使用して翻訳されました。
英語の元のコンテンツの最新バージョンを見るこのドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンクドキュメントのMarkdownをクリップボードにコピー
2026年に Lingui を使用して TanStack Start アプリケーションを国際化する方法
目次
Lingui とは?
Lingui は、マクロとメッセージ抽出を中心に構築された i18n ライブラリです。コンポーネント内にソーステキスト( t`Hello` 、<Trans>Hello</Trans>)を直接記述すると、lingui extract がすべてのメッセージをカタログ(デフォルトでは PO ファイル)に収集し、翻訳者がそれらを翻訳すると、Vite プラグインがコンパクトな JavaScript にコンパイルします。メッセージには ICU MessageFormat が使用されるため、複数形や選択分岐(select)もサポートされています。
TanStack Start には組み込みの i18n レイヤーが付属していないため、本ガイドではゼロから Lingui を組み込みます:
@rolldown/plugin-babelを介した Babel によるマクロのコンパイル(@vitejs/plugin-reactv6 および Vite 8 で必要)。- オプションの
{-$locale}セグメントによるロケールルーティング(/about、/fr/about)。 - ロケールごとに1つのカタログをオンデマンドでロードし、同時並行の SSR リクエストがロケールを共有しないようにレンダリングごとに
I18nインスタンスを作成。 - 完全な多言語 SEO:翻訳された
<title>と description、正規 URL(canonical)、x-default付きのhreflang、Open Graph ロケール、JSON-LD、サイトマップ、robots.txt、事前レンダリング、およびローカライズされた 404 ページ。
他のスタックをお探しですか? TanStack Start + use-intl ガイド、TanStack Start + Paraglide ガイド、または TanStack Start + Intlayer ガイドをご覧ください。
Next.js をお使いですか? Next.js + Lingui ガイドをご覧ください。ライブラリの比較については、Lingui vs Intlayer をお読みください。
TanStack Start における Lingui のベンチマーク結果
i18n ベンチマークでは、主要な各ライブラリを使用して同じ 10 ページ・10 ロケールの TanStack Start アプリを実行し、ブラウザが実際にダウンロードするサイズを測定しています。
動的な JSON 読み込み
実行時に翻訳を遅延読み込みします
スコープ付き JSON (ネームスペース)
ページごとの翻訳ネームスペース
I18n パフォーマンス ベンチマーク
この指標は何ですか?
国際化ライブラリバンドルの合計gzip圧縮サイズ。これには、ツリーシェイキングと縮小化(minification)後のプロバイダーとコンテンツ取得ロジックのみが含まれます。
なぜ重要なのか?
ライブラリのサイズが小さければ初期 JavaScript ペイロードが削減され、クライアント側でのダウンロードと実行が高速化されます।
表示形式
2026-09-26 に測定された @lingui/core@6.6.0 に関する主要な数値(gzip):
テーブルをモーダルで開き、すべてのデータを明確に表示
| セットアップ | ライブラリサイズ | ページごとの JS | 他ロケールの混入 | 他ページの混入 |
|---|---|---|---|---|
| i18n なし(ベースアプリ) | - | 111.0 KB | 0% | 0% |
| Lingui(本ガイドのセットアップ) | 56.7 KB | 115.2 KB | 9.3% | 0% |
@intlayer/lingui(互換アダプター) | 9.8 KB | 136.7 KB | 9.9% | 0% |
react-intlayer(ネイティブ Intlayer) | 4.5 KB | 126.8 KB | 0% | 0% |
注目すべきポイント:
- ロケールごとに1つのカタログをオンデマンドでロードする。 これにより、ページサイズをベースアプリに近い状態に保つことができます。
- ランタイムが依然として大きめである(約 57 KB gzip)。
@intlayer/lingui互換アダプター(ステップ 16)を使用すると、マクロをそのまま維持しながら約 10 KB まで削減できます。
詳細なデータについては、TanStack Start ベンチマークレポートおよびベンチマークリポジトリをご覧ください。
TanStack Start における機能比較
TanStack Start で一般的に使用される他のライブラリとの Lingui の比較:
テーブルをモーダルで開き、すべてのデータを明確に表示
| 機能 | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| コンポーネントの近くに翻訳を配置 | ✅ コロケーション | ❌ 一元管理された JSON | ❌ ロケールごとに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 ガイド:use-intl、Paraglide JS、および Intlayer。
推奨されるベストプラクティス
- ルートロケールから
<html>のlangとdirを設定する:サーバー HTML の時点で正しく出力されるようにします。 - プレフィックス付きでロケールごとに1つの URL を維持する:すべての言語バージョンが検索エンジンにインデックスされるようにします。
- ロケールごとに1つの
I18nインスタンスを作成する:SSR 中にグローバルインスタンスを変更してはいけません。同時に実行される2つのリクエストがお互いのロケールを上書きしてしまう恐れがあります。 - アクティブなカタログのみをロードする:クライアントコード内ですべてのカタログを一括インポートしないでください。
- 1つのマクロスタイルを選択して統一する(コンポーネント内では
useLingui+t、遅延記述子にはmsg)。t、i18n._、i18n.t、<Trans>を混在させると、人間にとっても AI アシスタントにとってもコードが読みにくくなります。 - CI で
lingui extractを実行する:新しいメッセージが未翻訳のままリリースされるのを防ぎます。 - メタデータを翻訳する:すべてのページで
canonical、hreflang、x-defaultを宣言します。 - 多言語対応のサイトマップと robots.txt を生成する:すべてのロケールを事前レンダリングします。
- 言語切り替えには本物のリンクを使用する:クローラーがすべての言語を発見できるようにします。
国際化と SEO に関するガイドおよび hreflang ガイドも併せてご覧ください。
TanStack Start アプリケーションで Lingui をセットアップするためのステップバイステップガイド
作成するプロジェクト構造は以下の通りです:
コードをクリップボードにコピー
依存関係のインストール
bashコードをコピーコードをクリップボードにコピー
- @lingui/core / @lingui/react:ランタイム、
I18nProvider、およびマクロ(@lingui/core/macro、@lingui/react/macro)。 - @lingui/cli:メッセージをカタログに収集するための
lingui extract。 - @lingui/vite-plugin:インポート時に
.poカタログをコンパイルするため、lingui compileを実行する必要がなくなります。 - @lingui/babel-plugin-lingui-macro + @rolldown/plugin-babel:ビルド時にマクロを変換します。
- @lingui/core / @lingui/react:ランタイム、
ロケール設定の一元管理
デフォルトロケールにはプレフィックスを付けず(
/about)、その他のロケールにはプレフィックスを付けます(/fr/about)。src/i18n/config.tsコードをコピーコードをクリップボードにコピー
Lingui の設定
Lingui の設定でも同じロケールリストを再利用するため、カタログ、ルーター、サイトマップの間で不整合が発生することはありません。
lingui.config.tsコードをコピーコードをクリップボードにコピー
抽出用スクリプトを追加します:
package.jsonコードをコピーコードをクリップボードにコピー
i18n:checkは、抽出およびコミットされていないメッセージがコンポーネントに含まれている場合に CI で失敗します。Vite の設定
@vitejs/plugin-reactv6 では Babel が組み込まれなくなりました。@rolldown/plugin-babelが Lingui マクロプラグインを実行し、linguiTransformerBabelPresetはマクロをインポートしているファイルのみを処理するため、高速なビルドが維持されます。vite.config.tsコードをコピーコードをクリップボードにコピー
ロケールごとのカタログロード
import()内のテンプレートリテラルにより、Vite はカタログごとに1つのチャンクを出力し、Lingui プラグインが.poファイルをそこにコンパイルします。フランス語の訪問者はフランス語のカタログのみをダウンロードします。コンパイルされたメッセージは純粋なデータであるため、ルートローダーから返却して HTML 内にシリアライズし、ハイドレーション時に再利用できます。
src/i18n/lingui.tsコードをコピーコードをクリップボードにコピー
TypeScript が
.poのインポートを受け付けるように、型定義を1回宣言します:src/i18n/po.d.tsコードをコピーコードをクリップボードにコピー
ルートドキュメントの作成
ルート(Root)ルートはオプションのロケールパラメータを読み取り、サーバーレンダリングされる
<html>にlangとdirを設定します。src/routes/__root.tsxコードをコピーコードをクリップボードにコピー
ロケールレイアウトルートの作成
{-$locale}フォルダはオプションのパスセグメントを作成します。/aboutと/fr/aboutは両方とも/{-$locale}/aboutにマッチします。レイアウトは未知のプレフィックスを拒否し、現在のロケールのカタログをロードして専用のI18nインスタンスを提供します。src/routes/{-$locale}/route.tsxコードをコピーコードをクリップボードにコピー
ページ内での翻訳の利用
コンポーネント内にソーステキストを記述します。マクロはビルド時にそれをメッセージ ID に変換し、
lingui extractがそれを収集します。- ネストされた要素を含む JSX コンテンツには
<Trans> - 文字列(属性、props)には
useLingui().t - ICU 複数形には
<Plural>
src/routes/{-$locale}/about.tsxコードをコピーコードをクリップボードにコピー
カタログの動的
import()はモジュールシステムによってキャッシュされるため、複数のローダーでloadI18nを呼び出してもカタログが2回ダウンロードされることはありません。- ネストされた要素を含む JSX コンテンツには
メッセージの抽出と翻訳
抽出を実行します。Lingui は各ロケールカタログにすべてのメッセージを書き出します:
bashコードをコピーコードをクリップボードにコピー
次に、各エントリの
msgstrを翻訳します:src/locales/fr/messages.poコードをコピーコードをクリップボードにコピー
src/locales/es/messages.poコードをコピーコードをクリップボードにコピー
デフォルトでは、メッセージ ID はソーステキストのハッシュです。英語テキストを変更すると新しいメッセージが作成されます。頻繁に変更されるテキストには、明示的な ID(
<Trans id="about.title">About us</Trans>)を使用してください。ローカライズされた Link コンポーネントの構築
オプションすべてのルートは
{-$locale}の下にあるため、リンクには現在のロケールパラメータを引き渡す必要があります。src/components/LocalizedLink.tsxコードをコピーコードをクリップボードにコピー
コンテンツの言語切り替え
オプションクローラーがすべての言語バージョンを発見できるように、スイッチャーはリンクとしてレンダリングします。
to="."は現在のページを維持しながらロケールパラメータを置き換えます。その後、ロケールレイアウトのローダーが新しいカタログを取得します。src/components/LocaleSwitcher.tsxコードをコピーコードをクリップボードにコピー
メタデータの国際化
オプション各ページが翻訳された
<title>と description、自己参照の canonical、ロケールごとのhreflangに加えてx-default、Open Graph ロケール、およびinLanguage付きの JSON-LD を提供していれば、各言語バージョンが個別に検索順位を獲得できます。メタデータはローダーで翻訳され(ステップ 8)、このヘルパーが残りを構築します:src/i18n/seo.tsコードをコピーコードをクリップボードにコピー
サイトマップと robots.txt の国際化
オプションサイトマップには全ロケールのすべての URL が一覧表示され、各エントリは
xhtml:linkで代替言語(alternates)を宣言します。robots.txtはすべての言語でプライベートルートをブロックし、サイトマップを指定します。スターターによって作成されたpublic/robots.txtが存在する場合は削除してください。src/routes/sitemap[.]xml.tsコードをコピーコードをクリップボードにコピー
src/routes/robots[.]txt.tsコードをコピーコードをクリップボードにコピー
すべてのロケールの事前レンダリング
オプションTanStack Start がビルド時にすべての言語バージョンを事前レンダリングできるように、ローカライズされたすべてのパスを一覧化します:
vite.config.tsコードをコピーコードをクリップボードにコピー
初回訪問者のリダイレクトと 404 ページの処理
オプションリクエストミドルウェアにより、
/にアクセスした訪問者を希望する言語にリダイレクトします(Cookie を優先し、次にAccept-Language)。ディープリンクはリダイレクトされないため、クローラーや共有された URL は常にリクエストされた通りのページを取得します。src/i18n/negotiateLocale.tsコードをコピーコードをクリップボードにコピー
src/start.tsコードをコピーコードをクリップボードにコピー
404 ページについては、キャッチオールルートがレイアウトのローカライズされた
notFoundComponentをレンダリングします。noindexを指定してください。React 19 が<meta>を<head>にホイスティングします。src/components/NotFound.tsxコードをコピーコードをクリップボードにコピー
src/routes/{-$locale}/$.tsxコードをコピーコードをクリップボードにコピー
マクロを維持したまま Intlayer でランタイムを軽量化
オプション@intlayer/lingui互換アダプターを使用すると、ソースコードを変更する必要がありません。マクロはこれまで通りコンパイルされ、生成されたi18n._()、useLingui()、および<Trans>の呼び出しはコンパイルされた Intlayer 辞書によって処理されます。ベンチマークでは、ランタイムが 約 56.7 KB から約 9.8 KB(gzip)に減少します。bashコードをコピーコードをクリップボードにコピー
マクロ変換の後にプラグインを追加し、
@lingui/coreと@lingui/reactをアダプターにエイリアスします:vite.config.tsコードをコピーコードをクリップボードにコピー
カタログは JSON 同期プラグイン(JSON カタログ)または PO 同期プラグイン(PO カタログ)と同期されます。詳細なセットアップについては Lingui 互換ガイドを、詳細な比較については Lingui vs @intlayer/lingui をご覧ください。
Intlayer を使用した翻訳の自動化
オプションLingui はメッセージを抽出しますが、何十ものカタログを手作業で入力することに多くの時間が費やされます。Intlayer は無料かつオープンソースであり、そのツール群は Lingui と併用して動作します:
- 独自の API キーとプロバイダーを使用した AI 翻訳。自動入力および CLI をご覧ください。
- PO 同期プラグインにより PO ファイルを信頼できる唯一の情報源(SSOT)として維持。
- CI での未翻訳メッセージのテスト。翻訳のテストをご覧ください。
- scan コマンドによりデプロイされたサイトを監査し、欠落している
hreflang、誤った canonical、ロケール混入を検出。
よくある質問
はい。Lingui には専用の TanStack Start 統合はありませんが、その Vite プラグインと Babel マクロプラグインはそのまま動作します。注意すべき2つのポイントは、@rolldown/plugin-babel を介してマクロを実行すること(Vite 8 および @vitejs/plugin-react v6 には Babel が含まれなくなったため)、および SSR 中にグローバルなインスタンスをアクティブ化するのではなくロケールごとに I18n インスタンスを作成することです。
サーバー上では、1つのプロセスが同時に多くのリクエストをレンダリングします。共有オブジェクト上で i18n.activate("fr") を呼び出すと、並行して英語でレンダリングされているリクエストの言語が切り替わってしまいます。setupI18n はロケールごとに独立したインスタンスを作成するため安全です。
いいえ。@lingui/vite-plugin は .po カタログがインポートされたときにコンパイルします。新しいメッセージを収集するために lingui extract を実行するだけで済みます。
msg マクロで宣言し、ルートローダー内で i18n._(msg`...`) を使用して翻訳します。ローダーは単純な文字列を返すため、head() は同期処理のまま維持され、値はハイドレーションのためにシリアライズされます。ステップ 8 とステップ 12 に完全なセットアップを示しています。
ベンチマークでは、ランタイムが約 56.7 KB(gzip)と測定されています。ロケールごとに1つのカタログをオンデマンドでロードする場合、i18n なしの 111 KB に対してページサイズは約 115 KB になります。すべてのカタログを静的にインポートすると約 152 KB に増加します。
はい。@intlayer/lingui アダプターはマクロを維持し、ランタイムを置き換えます。その後、コンポーネントを1つずつ useIntlayer に移行できます。互換アダプターをご覧ください。
コメント
まだコメントはありません。最初のコメントを共有しましょう。
