このページとあなたの好きなAIアシスタントを使ってドキュメントを要約します
バージョン履歴
- "初期バージョン"v9.5.102026/9/26
このページのコンテンツはAIを使用して翻訳されました。
英語の元のコンテンツの最新バージョンを見るこのドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンクドキュメントのMarkdownをクリップボードにコピー
2026年にuse-intlを使用してTanStack Startアプリケーションを国際化する方法
目次
use-intlとは?
use-intlは、next-intlのフレームワークに依存しないコアパッケージです。Next.jsへの依存なしに、同じuseTranslations、useFormatter、IntlProvider API、ICU MessageFormatのサポート、強力なTypeScript統合を提供します。そのため、TanStack Startアプリケーションを翻訳する際の最も一般的な選択肢の1つであり、このスタックに対してAIアシスタントが最も頻繁に提案するライブラリです。
TanStack Startには組み込みのi18nレイヤーが付属していません。ルーティング、ロケール検出、SEOメタデータ、サイトマップの生成は開発者自身が実装する必要があります。このガイドでは、それらすべてをエンドツーエンドで網羅しています。
- オプションの
{-$locale}セグメントによるロケール対応ルーティング(/about、/fr/about)。 - ページが必要なネームスペースとレンダリングするロケールのみをダウンロードするルートごとのメッセージ読み込み。
- テキストの不一致(ハイドレーションエラー)が発生しないサーバーレンダリングとハイドレーション。
- 完全な多言語SEO: 翻訳された
<title>と説明文、カノニカルURL、x-default付きのhreflang代替タグ、Open Graphロケール、JSON-LD、xhtml:link代替タグ付きサイトマップ、robots.txt、およびすべてのロケールの事前レンダリング(プリレンダリング)。
他のスタックをお探しですか?TanStack Start + Paraglideガイド、TanStack Start + Linguiガイド、またはTanStack Start + Intlayerガイドをご覧ください。
代わりにNext.jsをお使いですか?next-intlガイドをご覧ください。
TanStack Startにおけるuse-intlのベンチマーク結果
i18nベンチマークでは、同じ10ページ・10ロケールのTanStack Startアプリを主要な各ライブラリで実行し、ブラウザが実際にダウンロードするサイズを測定しています。
動的な JSON 読み込み
実行時に翻訳を遅延読み込みします
スコープ付き JSON (ネームスペース)
ページごとの翻訳ネームスペース
I18n パフォーマンス ベンチマーク
この指標は何ですか?
国際化ライブラリバンドルの合計gzip圧縮サイズ。これには、ツリーシェイキングと縮小化(minification)後のプロバイダーとコンテンツ取得ロジックのみが含まれます。
なぜ重要なのか?
ライブラリのサイズが小さければ初期 JavaScript ペイロードが削減され、クライアント側でのダウンロードと実行が高速化されます।
表示形式
2026-09-26に測定されたuse-intl@4.14.2の主要な数値(gzip):
テーブルをモーダルで開き、すべてのデータを明確に表示
| 構成 | ライブラリサイズ | ページごとのJS | 他ロケールの漏洩 | 他ページの漏洩 |
|---|---|---|---|---|
| i18nなし(ベースアプリ) | - | 111.0 KB | 0% | 0% |
use-intl(本ガイドの構成) | 75.9 KB | 128.7 KB | 0% | 0% |
@intlayer/use-intl(互換レイヤー) | 6.7 KB | 129.4 KB | 0% | 0% |
react-intlayer(ネイティブIntlayer) | 4.5 KB | 126.8 KB | 0% | 0% |
重要なポイント:
- メッセージをページごとに分割し、ロケールごとにロードする。 これにより両方の漏洩が解消されます。これが以下のステップで実装する構成です。
- ランタイム自体が重いまま(gzipで約76 KB)。これはICUパーサーがクライアントに送信されるためです。
@intlayer/use-intl互換アダプター(ステップ17)を使用すると、まったく同じAPIを維持しながらランタイムを約7 KBに抑えることができます。
詳細なデータについては、TanStack Startベンチマークレポートおよびベンチマークリポジトリをご覧ください。
TanStack Startでの機能比較
use-intlとTanStack Startで一般的に使用される他のライブラリとの比較:
テーブルをモーダルで開き、すべてのデータを明確に表示
| 機能 | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| コンポーネント近傍への翻訳配置 | ✅ コロケーション(同居) | ❌ 一元化されたJSON | ❌ ロケールごとに1つのJSONファイル | ⚠️ コンポーネント内のソーステキスト |
| TypeScript統合 | ✅ 自動生成される型 | ✅ AppConfig経由 | ✅ 型付きメッセージ関数 | ⚠️ マクロのみ |
| 翻訳漏れの検出 | ✅ 型エラーおよびビルド警告 | ⚠️ ランタイムフォールバック | ⚠️ ベースロケールにフォールバック | ⚠️ ソーステキストにフォールバック |
| リッチコンテンツ(JSX、Markdown) | ✅ 直接サポート | ⚠️ t.rich経由のタグ | ⚠️ 文字列のみ | ✅ <Trans>内のJSX |
| ローカライズされたルーティング | ✅ 組み込み | ❌ 手動の{-$locale} | ✅ urlPatterns + ルーター書き換え | ❌ 手動の{-$locale} |
| リロードなしのロケール切り替え | ✅ 可能 | ✅ 可能 | ❌ フルページリロード | ✅ 可能 |
| 複数形処理(Pluralization) | ✅ 列挙ベース | ✅ 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、Paraglide JS、およびIntlayer。
推奨されるプラクティス
<html>にlangとdirを設定する: アクセシビリティ、スクリーンリーダー、検索エンジンのために重要です。- ロケールごとに1つのURLを維持する: クッキーのみによる切り替えではなく、ロケールプレフィックス(
/fr/about)を使用して、翻訳されたすべてのページがクロールおよび共有可能になるようにします。 - ネームスペースごとにメッセージを分割する(
common、home、about): ルートごとにロードします。 - アクティブなロケールのみをロードする: クライアントに配信されるモジュールで、すべてのロケールファイルを一括インポートしないでください。
IntlProviderでタイムゾーンを固定する: そうしないと、SSR時はサーバーのタイムゾーンで日付がフォーマットされ、ハイドレーション時は訪問者のタイムゾーンでフォーマットされるため、ハイドレーションの不一致が発生します。- メタデータを翻訳する: すべてのページで
canonical、hreflang、x-defaultを宣言します。 - 多言語サイトマップとrobots.txtを生成する: すべてのロケールを事前レンダリングします。
- 言語切り替えには
<select>ではなく本物のリンクを使用する: クローラーがすべての言語を発見できるようにします。 - メッセージに型を付ける: 存在しないキーをコンパイル時に検出できるようにします。
詳細は国際化とSEOのガイドおよびhreflangガイドをご覧ください。
TanStack Startアプリケーションでuse-intlをセットアップするステップバイステップガイド
作成するプロジェクト構造は以下のとおりです:
コードをクリップボードにコピー
依存関係のインストール
TanStack Startプロジェクトから始めて、
use-intlを追加します:bashコードをコピーコードをクリップボードにコピー
- use-intl:
IntlProvider、useTranslations、useFormatter、およびcreateTranslator(Reactの外部、たとえばhead()などで使用可能)を提供します。
- use-intl:
ロケール設定の一元化
ロケールとURLヘルパーのための唯一の信頼できる情報源(Single Source of Truth)を作成します。他のすべてのファイル(ルート、SEO、サイトマップ、事前レンダリング)はここからインポートするため、新しいロケールの追加が1行の変更で済みます。
デフォルトロケールはプレフィックスなし(
/about)のままにし、他のロケールにはプレフィックス(/fr/about)を付けます。これは「必要に応じた(as-needed)」戦略であり、ロケールごとにページあたり1つのURLを保ちつつ、主要な読者層に対して短いURLを提供します。src/i18n/config.tsコードをコピーコードをクリップボードにコピー
翻訳ファイルの作成
ロケールごと、およびネームスペースごとにメッセージを整理します。
commonにはすべてのページに必要なもの(ナビゲーション、フッター)を配置し、各ページにはメタデータを含めた独自のファイルを配置します。use-intlはICU MessageFormatを使用するため、複数形、条件分岐(select)、フォーマット済み引数はメッセージ内に直接記述します。
messages/en/common.jsonコードをコピーコードをクリップボードにコピー
messages/en/about.jsonコードをコピーコードをクリップボードにコピー
messages/fr/common.jsonコードをコピーコードをクリップボードにコピー
messages/fr/about.jsonコードをコピーコードをクリップボードにコピー
同様に、
metadataオブジェクトとページコンテンツを含むhome.jsonを作成します。ネームスペースおよびロケールごとのメッセージ読み込み
このローダーはパフォーマンスにおいて最も重要なファイルです。
import.meta.globはViteに対してJSONファイルごとに1つのチャンクを出力するよう指示します。フランス語で["about"]を要求するルートはmessages/fr/about.jsonのみをダウンロードし、それ以外はダウンロードしません。これにより、ベンチマークでロケール漏洩0%およびページ漏洩0%を達成しています。src/i18n/messages.tsコードをコピーコードをクリップボードにコピー
メッセージの型付け
モジュール拡張(Module augmentation)により、
useTranslations("about")やt("counter.label")の自動補完が有効になり、タイポや削除されたキーに対してコンパイルエラーが発生するようになります。src/i18n/use-intl.d.tsコードをコピーコードをクリップボードにコピー
tsconfig.jsonでresolveJsonModuleが有効になっていることを確認してください。ルートドキュメントの作成
ルート(Root)ルートは
<html>をレンダリングします。オプションのロケールパラメータを読み取ってlangとdirを設定するため、JavaScriptが実行される前のサーバーレンダリングされたHTMLの段階で属性が正しく設定されます。src/routes/__root.tsxコードをコピーコードをクリップボードにコピー
ロケールレイアウトルートの作成
{-$locale}フォルダはオプションのパスセグメントを作成します。/aboutと/fr/aboutの両方が/{-$locale}/aboutにマッチします。このレイアウトは以下の処理を行います:- サポートされていないプレフィックスを拒否(
/xx/about→ 404)。 - 現在のロケールに対応する
commonネームスペースのみをロード。 IntlProviderを通じてメッセージを提供。
ローダーの結果はHTMLにシリアライズされてハイドレーション時に再利用されるため、クライアントが
common.jsonを再度ダウンロードすることはありません。staleTime: Infinityにより、クライアント側のナビゲーション間でもキャッシュが保持されます。src/routes/{-$locale}/route.tsxコードをコピーコードをクリップボードにコピー
IntlProviderは親プロバイダーからのメッセージを自動でマージしません。次のステップでマージを行う小さなコンポーネントを追加し、各ページがcommonの上に独自のネームスペースを追加できるようにします。- サポートされていないプレフィックスを拒否(
ページメッセージのスコープ設定
各ページはそのローダーで独自のネームスペースをロードし、コンテンツを
ScopedMessagesでラップします。これにより、ページのネームスペースが親のメッセージとマージされます。src/components/ScopedMessages.tsxコードをコピーコードをクリップボードにコピー
ページ内での翻訳の利用
ページローダーは現在のロケールの
aboutネームスペースを取得し、head()はそのメッセージから翻訳された完全なSEOメタデータを構築し(ステップ13を参照)、コンポーネントがコンテンツをレンダリングします。src/routes/{-$locale}/about.tsxコードをコピーコードをクリップボードにコピー
コンポーネントでの翻訳とフォーマッターの使用
プロバイダー配下の任意のコンポーネントで
useTranslationsとuseFormatterを呼び出すことができます。複数形はICUによって解決され、数値はアクティブなロケールに従ってフォーマットされます。src/components/Counter.tsxコードをコピーコードをクリップボードにコピー
ローカライズされたLinkコンポーネントの作成
オプションすべてのルートは
{-$locale}の下に存在するため、リンクには現在のロケールパラメータを含める必要があります。このラッパーはTanStack Routerの型付けされたtoを保持しつつ、ロケールを自動で挿入します。src/components/LocalizedLink.tsxコードをコピーコードをクリップボードにコピー
src/components/Header.tsxコードをコピーコードをクリップボードにコピー
コンテンツの言語切り替え
オプション言語スイッチャーは
<select>ではなくリンクとしてレンダリングします。リンクはクロール可能であるため、検索エンジンがすべての言語バージョンを発見でき、JavaScriptなしでも機能します。to="."は現在のページを維持し、ロケールパラメータのみを置き換えます。クッキーはステップ16のリダイレクトミドルウェア用に明示的な選択を記憶します。src/components/LocaleSwitcher.tsxコードをコピーコードをクリップボードにコピー
メタデータの国際化
オプションここがi18nの真価を発揮するポイントです。各言語バージョンが個別に検索順位を獲得できるようになります。すべてのページで以下を公開する必要があります:
- 翻訳された
<title>とdescription - 自身を指す(デフォルトロケールではなく)カノニカル(canonical) URL
- ロケールごとに1つの
hreflang代替タグ、および一致する言語がない場合のx-default - ソーシャルプレビューで使用されるOpen Graphの
og:locale、og:locale:alternate、og:url - 検索エンジンやAIアシスタントがページの言語を判定するのに役立つ
inLanguage付きのJSON-LD
単一のヘルパー関数ですべてを構築できるため、各ページの実装を簡潔に保てます:
src/i18n/seo.tsコードをコピーコードをクリップボードにコピー
ステップ9で示したように、すべてのページの
head()でこれを使用します。ホームページの場合はpath: "/"を渡します。- 翻訳された
サイトマップの国際化
オプション多言語サイトマップにはすべてのロケールのすべてのURLがリストされ、各エントリは
xhtml:linkでそのすべての代替言語を宣言します。Googleはこれらのアノテーションをページのhreflangタグとまったく同様に使用するため、ページのクロール頻度が低い場合の信頼性の高いバックアップになります。TanStack Startのサバールートを使用すると、ファイルルートからサイトマップを配信できます:
src/routes/sitemap[.]xml.tsコードをコピーコードをクリップボードにコピー
robots.txtの国際化
オプションプライベートなルートはすべての言語に存在するため、
Disallowルールはすべてのプレフィックスをカバーする必要があります。スターターによってpublic/robots.txtが作成されている場合は削除し、ルートから配信します:src/routes/robots[.]txt.tsコードをコピーコードをクリップボードにコピー
初回来訪者を適切な言語にリダイレクト
オプションリクエストミドルウェアは、まずロケールクッキー、次に
Accept-Languageヘッダーに基づいて、/にアクセスした訪問者を希望の言語にリダイレクトします。リダイレクトされるのは/のみです。ディープリンクは変更されないため、共有URLやクローラーは常に要求されたページを直接取得できます。src/i18n/negotiateLocale.tsコードをコピーコードをクリップボードにコピー
src/start.tsコードをコピーコードをクリップボードにコピー
スイッチャーで明示的に英語を選択した訪問者にはクッキーに
locale=enが設定されるため、再度リダイレクトされることはありません。完全な静的デプロイメント(ステップ18)では、/はファイルとして配信され、このミドルウェアは実行されませんが、問題ありません。ページにはアクセス可能なままであり、スイッチャーで切り替えが可能です。use-intl APIを維持したままIntlayerでランタイムを削減
オプションベンチマークが示すように、use-intlセットアップで最も重い部分はランタイム自体です(gzipで約76 KB)。
@intlayer/use-intl互換アダプターは同じAPI(useTranslations、useFormatter、IntlProvider、createTranslator、ICU複数形、t.rich)を提供しながら、コンパイル済みのIntlayerディクショナリから配信します。コンポーネントを変更することなく、約75.9 KBから約6.7 KBに削減され、ロケール漏洩0%、ページ漏洩0%を実現します。bashコードをコピーコードをクリップボードにコピー
Viteプラグインは
use-intlをアダプターにエイリアスするため、既存のインポートコードはそのまま動作します:vite.config.tsコードをコピーコードをクリップボードにコピー
JSON同期プラグインにより、JSONファイルを引き続き信頼できる情報源として利用できます:
intlayer.config.tsコードをコピーコードをクリップボードにコピー
このアダプターはスムーズな移行パスにもなります。一度動作させれば、コンポーネントを1つずつネイティブの
useIntlayerAPIに移行できます。Intlayer TanStack Startガイドをご覧ください。すべてのロケールを事前レンダリング
オプション静的HTMLは最も高速に配信できるページであり、インデックス作成も最も容易です。ローカライズされたすべてのパスを指定して、TanStack Startがビルド時にすべての言語バージョン、サイトマップ、robotsファイルを事前レンダリングするようにします:
vite.config.tsコードをコピーコードをクリップボードにコピー
ロケールスイッチャーが実際のリンクをレンダリングするため、
crawlLinks: trueによってリストし忘れたページも自動的に検出されます。ローカライズされた404ページの処理
オプションステップ7のレイアウトは、未知のロケールプレフィックスに対して既に
notFound()をスローします。ロケール内の未知のパスでもローカライズされた404がレンダリングされるようにキャッチオールルートを追加し、noindexを設定します。React 19は<meta>タグを自動的に<head>に巻き上げます(hoist)。src/components/NotFound.tsxコードをコピーコードをクリップボードにコピー
src/routes/{-$locale}/$.tsxコードをコピーコードをクリップボードにコピー
サーバー関数でロケールにアクセス
オプションサーバー関数はルートパラメータを受け取りません。ローカライズされたメールの送信や言語設定の保存を行うには、ロケールクッキーを読み取り、
Accept-Languageヘッダーにフォールバックします:src/server/getServerLocale.tsコードをコピーコードをクリップボードにコピー
サーバー関数内で翻訳を行うには、これと
use-intlのloadMessagesおよびcreateTranslatorを組み合わせます。Intlayerを使用した翻訳作業の自動化
オプションuse-intlは翻訳をレンダリングしますが、翻訳を生成・管理する機能はありません。Intlayerは無料かつオープンソースであり、use-intlを使い続ける場合でもそのギャップを埋めることができます:
- CIや単体テストでの翻訳漏れテスト: 翻訳のテストをご覧ください。
- AIによる翻訳: 独自のAPIキーとプロバイダーを使用して、
npx intlayer fillがアプリの文脈を理解しながら不足しているキーを翻訳します。自動入力(auto fill)およびCLIをご覧ください。 - JSONファイルを信頼できる情報源として維持: JSON同期プラグインを使用します。
- ビジュアルなコンテンツ編集: ビジュアルエディターとCMSにより、非エンジニアでも翻訳を更新できます。
- AIエージェントへのコンテキスト提供: MCPサーバーとエージェントスキルを利用します。
- デプロイ済みサイトのスキャン: scanコマンドにより、
hreflangの欠落、誤ったカノニカル、ロケール漏洩を検出します。
すべての機能を確認するには、Intlayerのメリットをご覧ください。
よくある質問
はい、Next.js以外でnext-intlのAPIを使用したい場合には適しています。ICUメッセージ、フォーマッター、優れたTypeScriptサポートが提供され、setRequestLocaleなどのNext.js固有の制約を回避できます。トレードオフはライブラリの重さです。ベンチマークではランタイムが約76 KB(gzip)と測定されており、単純なセットアップではすべてのロケールやすべてのページがブラウザに配信されてしまいます。漏洩を防ぐために、本ガイドのようにルートごと、ロケールごとにネームスペースをロードしてください。
use-intlはnext-intlのコア部分です。next-intlはその上にNext.js固有の統合(ミドルウェア、ナビゲーションヘルパー、Server Components用のgetTranslations、リクエスト設定など)を追加したものです。TanStack Startではuse-intlを直接使用し、上記のようにTanStack Routerでルーティングを実装します。
URL内のプレフィックスを使用してください。これにより、各言語バージョンが固有のURLを持ち、検索エンジンがインデックス可能になり、ユーザーが共有できるようになります。明示的な選択を記憶するためにはクッキーも有用であり、ステップ16のリダイレクトミドルウェアで活用されています。
サーバーとブラウザで異なるタイムゾーンで日付がフォーマットされるためです。両側で同じテキストが生成されるよう、IntlProviderに明示的なtimeZoneを渡す(またはクッキーに保存された訪問者のタイムゾーンを渡す)ようにしてください。
まず、メッセージをネームスペースごとに分割し、import.meta.globを使用してルートごと・ロケールごとにロードします。これによりロケール漏洩とページ漏洩が解消されます。さらにランタイムサイズを削減したい場合は、@intlayer/use-intlアダプターに切り替えます。ベンチマークにおいて、同じAPIのまま約75.9 KBから約6.7 KBに削減されます。
ルートローダーから返されたメッセージを使用して、ルートのhead()関数内でcreateTranslatorを呼び出し、title、description、カノニカルリンク、hreflangリンクを返します。ステップ13で再利用可能なヘルパーを提供しています。
コメント
まだコメントはありません。最初のコメントを共有しましょう。
