このページとあなたの好きなAIアシスタントを使ってドキュメントを要約します
このページのコンテンツはAIを使用して翻訳されました。
英語の元のコンテンツの最新バージョンを見るこのドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンクドキュメントのMarkdownをクリップボードにコピー
next-intl VS Intlayer

next-intlはNext.jsで最も人気のあるi18nライブラリです。Intlayerはコンパイラベース、コンポーネントスコープの代替案です。どちらもApp Routerアプリケーションをローカライズします。問題は、アプリがビルドされた後、それぞれがどの程度のコストがかかるかということです。
この記事はチュートリアルではありません。Benchmark Bloomからの数値に基づいた比較です。Benchmark Bloomはオープンソースのベンチマークスイートで、各ライブラリで同じアプリケーションをビルドし、ブラウザが実際にダウンロードして実行するものを測定します。
tl;dr: 同じ Next.js アプリケーションで、next-intlは全ページで +12.6 KB gzip の JavaScript を追加しますが、Intlayer は +0.3 KB です。追加の作業なしで、next-intlは全ページで ~90% の外国語ページ文字列 を配信します。next-intlで 0% のリークを達成するには、namespace スコープと per-pagepick(messages, [...])が必要です。Intlayer はデフォルトで 0% に達します。なぜなら、そのコンパイラがコンテンツをコンポーネント単位でスコープするからです。next-intlAPI を Intlayer の出力で使いたい場合、@intlayer/next-intlアダプタは 1 ページあたり 147.5 KB と測定されたのに対し、元のものは 153.6 KB です。
要するに
- next-intl - 軽量でドキュメントが充実しており、ICU message format、App Router への first-class なサポート、middleware、formatters、navigation helpers を備えています。コンテンツは集中管理された JSON カタログに保存され、パフォーマンス最適化(namespaces、ページごとのメッセージ picking、lazy loading)はあなたの責任です。
- Intlayer - コンポーネント中心のコンテンツモデル。
.content.tsdictionaries はそれが提供するコンポーネントの隣に配置され、build-time compiler がコンポーネントごと、locale ごとに tree-shake と lazy-load を行い、厳密な TypeScript 型がコンテンツから生成され、翻訳漏れは build 時に失敗します。middleware、SEO helpers、Visual Editor / CMS、AI 支援翻訳機能を搭載しています。
テーブルをモーダルで開き、すべてのデータを明確に表示
バッジは自動的に更新されます。スナップショットは時間とともに変わります。
機能比較
テーブルをモーダルで開き、すべてのデータを明確に表示
| 機能 | next-intlayer (Intlayer) | next-intl |
|---|---|---|
| コンポーネント近くの翻訳 | ✅ はい、各コンポーネントに並置された .content.ts | ❌ いいえ、集中管理された messages/{locale}.json |
| TypeScript統合 | ✅ コンテンツから自動生成された厳密な型 | ✅ 良好、global.d.ts 拡張機能を使用してキーに型を付ける |
| 翻訳不足の検出 | ✅ TypeScriptエラー + ビルド時エラー/警告 | ⚠️ ランタイム フォールバック + コンソール警告 |
| リッチコンテンツ (JSX / Markdown / components) | ✅ 直接サポート | ⚠️ t.rich() / t.markup() タグプレースホルダー付き |
| ICU サポート | ⚠️ WIP | ✅ Yes |
| フォーマット (日付、数値、通貨) | ✅ useNumber, useDate, ... (内部的に Intl を使用) | ✅ useFormatter() (内部的に Intl を使用) |
| ローカライズされたルーティング & ミドルウェア | ✅ ビルトイン proxy/middleware、getMultilingualUrls | ✅ ビルトイン middleware、Link、redirect、usePathname |
| SEO ヘルパー (hreflang、sitemap、robots) | ✅ ビルトイン ヘルパー | ⚠️ 手動、ルーティング設定に基づく |
| 同期サーバーコンポーネント | ✅ next-intlayer/server の useIntlayer は任意の子サーバーコンポーネントで動作 | ⚠️ getTranslations は非同期; 同期子は t をプロップとして渡す必要がある |
| 静的レンダリング | ✅ 静的レンダリングをブロックしない | ⚠️ setRequestLocale() が必須; 名前空間付きカタログは、当社のテストでもページを静的レンダリングから除外する |
| Tree-shaking (使用済みコンテンツのみをシップ) | ✅ コンポーネントごと、ロケールごと、コンパイラによって自動化 | ⚠️ 手動: 名前空間 + ページごとの pick(messages, [...]) |
| 遅延読み込み | ✅ importMode: 'dynamic' (設定1行) | ⚠️ 手動: getRequestConfig での動的インポート |
| 未使用コンテンツの削除 | ✅ デッドな辞書はビルド時にドロップされます | ❌ 組み込みではありません |
| 翻訳の欠落をテスト (CLI / CI) | ✅ npx intlayer content test | ⚠️ 組み込みではありません; ドキュメントは npx @lingual/i18n-check を示唆しています |
| AI による翻訳 | ✅ 組み込み、独自のプロバイダーキーを使用します | ❌ いいえ |
| ビジュアルエディタ / CMS | ✅ 無料ビジュアルエディタ + オプションCMS | ❌ いいえ (外部ローカライゼーションプラットフォーム) |
| MCPサーバー & エージェントスキル | ✅ はい | ❌ いいえ |
| エコシステム / コミュニティ | ⚠️ より小規模だが急速に成長中 | ✅ 大規模、Next.jsの参照実装 |
ベンチマーク
測定内容
Benchmark Bloom スイートは、各ライブラリで同じアプリケーションをビルドします:10ページ(ホーム、アバウト、ブログ、キャリア、コンタクト、FAQ、プライシング、プロダクト、設定、チーム)、10ロケール(en、fr、es、de、it、pt、zh、ja、ko、ru)、同一のコンポーネントと同一のコンテンツ。ページはenとfrで測定されます。各ライブラリは、最も単純なセットアップから最適なセットアップまで、最大4つのロード戦略で実装されています:
テーブルをモーダルで開き、すべてのデータを明確に表示
| 戦略 | 説明 | これを行うのは |
|---|---|---|
| static | すべてのlocaleとすべてのページが一緒にバンドルされている | クイックプロトタイプ、AI生成コード |
| dynamic | アクティブなlocaleのみがロードされるが、すべてのページが一度にロードされる | ほとんどのプロジェクト |
| scoped-static | ルートごとのnamespaces、lazy loadingなし | まれ |
| scoped-dynamic | ルートごとのnamespaces + lazy loading。現在のページの現在のlocaleのみが送信される | 厳密なパフォーマンス予算を持つアプリ |
Intlayerには「scoped」バリアントがありません。compilerはコンテンツをコンポーネントごとに自動的にスコープするため、そのstaticとdynamicの行はすでにスコープされています。
各ビルドについて、スイートは以下を記録します:
- Lib size: i18n ライブラリのみをインポートする空のコンポーネントの gzip サイズ。ランタイムの固定コスト。
- Page JS: ページごとにダウンロードされた gzip JavaScript。すべてのページとロケール全体で平均化されます。
- Locale leak %: ダウンロードされた JS に含まれる翻訳文字列のうち、ユーザーが閲覧していないロケールに属する割合(
enとfrでフィンガープリント化されているため、50% は「他の測定されたロケールが完全に存在する」を意味します。10 個のロケールがバンドルされている場合、実際の無駄はさらに大きくなります)。 - Page leak %: ダウンロードされた JS に含まれる翻訳文字列のうち、ユーザーがいないページに属する割合。
- Component avg: 分離してコンパイルされた各コンポーネントの平均 gzip サイズ。単一のコンポーネントが i18n ランタイムをどの程度ドラッグインするかを示します。
- E2E reactivity: 新しいlocaleを選択してから、DOM内の
html[lang]が更新されるまでの実際の経過時間(Playwright、5回の反復)。 - Hydration: Reactのhydrationフェーズの継続時間。
以下の数字は、next-intl4.14.2、use-intl4.14.2、intlayer9.5.1を使用した2026-09-12実行日のものです。テストアプリケーションは意図的に小規模(locale あたり数十個の文字列)であるため、漏洩パーセンテージはパターンを説明します:コンテンツが増えるにつれて増加し、ランタイムコストは固定されたままです。
Next.js(App Router)の結果
関心のあるメトリクスとライブラリを選択してください:
指標
動的な JSON 読み込み
実行時に翻訳を遅延読み込みします
スコープ付き JSON (ネームスペース)
ページごとの翻訳ネームスペース
この指標は何ですか?
国際化ライブラリバンドルの合計gzip圧縮サイズ。これには、ツリーシェイキングと縮小化(minification)後のプロバイダーとコンテンツ取得ロジックのみが含まれます。
なぜ重要なのか?
ライブラリのサイズが小さければ初期 JavaScript ペイロードが削減され、クライアント側でのダウンロードと実行が高速化されます।
表示形式
テーブルをモーダルで開き、すべてのデータを明確に表示
| Library | Strategy | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity | Hydration |
|---|---|---|---|---|---|---|---|---|
| base (i18n なし) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
next-intl | static | 14.7 KB | 153.6 KB | 4.2% | 89.8% | 21.8 KB | 16.0 ms | 14.7 ms |
next-intl | dynamic | 14.7 KB | 153.6 KB | 9.7% | 89.9% | 21.8 KB | 15.6 ms | 14.8 ms |
next-intl | scoped-static | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 80.1 KB | 17.9 ms | 17.4 ms |
next-intl | scoped-dynamic | 14.7 KB | 153.6 KB | 0.0% | 0.0% | 22.9 KB | 17.8 ms | 16.8 ms |
next-intlayer | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
next-intlayer | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
@intlayer/next-intl (compat) | static | 8.0 KB | 147.5 KB | 0.0% | 0.0% | 8.1 KB | 14.5 ms | 12.8 ms |
@intlayer/next-intl (compat) | dynamic | 8.0 KB | 148.7 KB | 0.0% | 0.0% | 8.1 KB | 11.7 ms | 12.8 ms |
読み方
- ランタイムコスト。 ベースアプリケーションのサイズはページあたり 141.0 KB です。
next-intlはこれを 153.6 KB に増加させます(毎ページ +12.6 KB gzip)、Intlayer は 141.3 KB に増加させます(+0.3 KB)。このギャップは、文字列がいくつあるかに依存しません。これはライブラリランタイムです。 - Leakage. 最も一般的に使用されている2つのセットアップ(
staticとdynamic)では、next-intlはすべてのページに外国語ページの文字列の約90%を配信します。つまり、すべてのen.jsonがクライアントプロバイダーに組み込まれます。0%に達するには、scoped-*セットアップが必要です。カタログを名前空間に分割し、各ページで正しいものをpick()します。Intlayerは、そのような手段なしに両方の行で0%です。 next-intlのページごとのJSは戦略間で変わりませんでした。 テストコンテンツが小さいため、ここでは~90%のleakはわずか数KBです。実際のアプリで1ページあたり数百の文字列がある場合、その比率が主要なコストになります。一方、+12.6 KBのランタイムはすべての設定で支払われます。- コンポーネントサイズ。
useTranslations()を呼び出すコンポーネントは平均21.8 KBにコンパイルされ、useIntlayer()を使用した同じコンポーネントは6.9 KBにコンパイルされます。scoped-staticセットアップでは、各コンポーネントがそのnamespace catalogをインラインで含めるため、next-intlコンポーネントは80.1 KBにジャンプします。 - リアクティビティとhydrationは、Next.js上の両方のライブラリで同じ範囲内です(15-18 ms)。ここではどちらもボトルネックではありません。
すべてのライブラリと戦略を含む完全な表は、Next.js ベンチマークレポートにあります。
TanStack Startでの結果(use-intl)
use-intlはnext-intlのframework-agnosticなコアです。同じAPI、同じメッセージフォーマット。TanStack Startでintlayerと比較することで、方程式からNext.js固有の部分を削除します。
テーブルをモーダルで開き、すべてのデータを明確に表示
| Library | Strategy | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity |
|---|---|---|---|---|---|---|---|
| base (i18n なし) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms |
use-intl | static | 14.1 KB | 179.8 KB | 50.0% | 89.8% | 76.0 KB | 6.7 ms |
use-intl | dynamic | 14.1 KB | 119.4 KB | 0.0% | 89.8% | 75.9 KB | 7.0 ms |
use-intl | scoped-static | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 20.9 ms |
use-intl | scoped-dynamic | 14.1 KB | 128.7 KB | 0.0% | 0.0% | 87.1 KB | 13.3 ms |
intlayer | static | 5.0 KB | 125.8 KB | 50.0% | 0.0% | 8.1 KB | 3.2 ms |
intlayer | dynamic | 5.0 KB | 118.6 KB | 0.0% | 0.0% | 6.3 KB | 3.6 ms |
@intlayer/use-intl (compat) | dynamic | 7.3 KB | 129.7 KB | 0.0% | 0.0% | 9.3 KB | 8.7 ms |
読み方
- 素朴な
use-intlセットアップは、ベースアプリより ページあたり 68.8 KB 多い JS を配信しており、文字列の半分は間違ったロケールに属し、90% は間違ったページに属しています。 use-intlのdynamicモードは119.4 KBに達し、Intlayerの118.6 KBに近いですが、それでも89.8%のページリークを抱えています:アクティブなロケールのすべてのページの文字列がすべてのページで読み込まれます。それらをルートごとにスコープする(scoped-*)リークを削除しますが、さらに約9 KBのチャンク オーバーヘッドが必要です。- Intlayerの
static行は既に0%のページリークがあります:コンパイラはページ上のコンポーネントで使用されている辞書のみをバンドルします。intlayer.config.tsで1行のimportMode: 'dynamic'を有効にすると、ロケールリークも削除されます。 - コンポーネントサイズはアーキテクチャが表れる場所です:
use-intlではコンポーネントあたり76~87 KB対Intlayerの6~8 KB。useTranslations()は各コンポーネントをグローバルメッセージツリーにバインドします。useIntlayer()はそれを独自の辞書にバインドします。 - ロケール切り替えは Intlayer で 2 倍~4 倍高速化されています(3 ms 対 7-21 ms)。
完全な表は TanStack Start ベンチマークレポート にあります。
なぜギャップがあるのか?集中型カタログ vs コンパイル済み辞書

next-intl は従来のモデルに従います:ロケールごとに 1 つの JSON、getRequestConfig で読み込み、NextIntlClientProvider にプッシュされ、t("namespace.key") で読まれます。
コードをクリップボードにコピー
ランタイムはページがどのキーを使用するかを知ることができないため、安全なデフォルトはカタログ全体を送信することです。最適化するには、あなたがカタログを namespace に分割し、あなたが各ページに必要な namespace を決定し、あなたがコンポーネントが移動するにつれてそのマッピングを同期させ続ける必要があります。ベンチマークの scoped-dynamic 行はその作業の報酬であり、ほとんどのチームはそこに到達しません。
その最適化を行わない場合のコストは、ページ数とロケール数の2つの軸で同時に増大します:

Intlayer は責任を逆転させます。コンテンツはコンポーネントの隣に宣言されます:
コードをクリップボードにコピー
ビルド時に、コンパイラ (@intlayer/swc / @intlayer/babel) はどのコンポーネントがどの辞書をインポートしているかを認識します。これらの辞書をバンドルし、アクティブなロケールのみを対象とし、何もインポートしていないものは削除されます。「scoped-dynamic」パターンは、チームが維持しなければならない規律ではなく、ビルドの出力になります。
dynamic行の数値を取得するには、intlayer.config.tsでdictionary.importMode: 'dynamic'を設定してください。bundle optimization doc を参照してください。
開発者体験
Client component
コードをクリップボードにコピー
コードをクリップボードにコピー
このコンポーネントをレンダリングするすべてのページで、NextIntlClientProviderに渡されるメッセージにcounter名前空間を含めることを忘れないでください。
コードをクリップボードにコピー
コードをクリップボードにコピー
ページに登録する必要はありません。コンポーネントが独自のコンテンツを提供します。
同期サーバーコンポーネント
Design-system pieces (navbar, footer, cards) はしばしば client components の子として render される server components であるため、async にすることはできません。
コードをクリップボードにコピー
ページは await getTranslations("counter") と await getFormatter() を実行し、その結果を props として下に渡す必要があります。コンポーネントはもはや self-contained ではありません。
コードをクリップボードにコピー
メタデータ
コードをクリップボードにコピー
コードをクリップボードにコピー
next-intl API を維持しながら Intlayer の出力を取得する
ベンチマーク結果を得るためにコンポーネントを書き換える必要はありません。@intlayer/next-intl はドロップイン アダプターです。useTranslations、getTranslations、useFormatter、t.rich()、ICU複数形、および next-intl/navigation ヘルパーを保持し、Intlayer コンパイラでコンパイルされた Intlayer辞書から提供します。
コードをクリップボードにコピー
ベンチマークにおいて、同じアプリの互換ビルドは、アプリケーションコードに一切手を加えることなく、ページあたり 153.6 KB から 147.5 KB、コンポーネントあたり 21.8 KB から 8.1 KB、ページリークは 約90% から 0% へと改善しました。既存の messages/{locale}.json ファイルは、JSON 同期プラグイン を通じて信頼できる情報源として維持できます。
ステップバイステップの手順については、next-intl 移行ガイド を参照してください。
どちらを選ぶべきか?
Next.js のエコシステム標準を求め、ICU MessageFormat に依存しており、アプリが中小規模であるか、集中型 JSON を前提とする翻訳プラットフォーム(Crowdin、Phrase、Lokalise...)と連携する場合。パフォーマンスを重視するなら、カタログをネームスペースに分割し、ページごとに pick() でメッセージを選別する工数を確保してください。
すでに next-intl を導入しており、コードを書き直すことなくバンドルサイズの削減効果を得たい場合。互換アダプターにより、既存のインポートと messages/{locale}.json ファイルを信頼できる唯一の情報源として維持できます。next-intl vs @intlayer/next-intl で直接比較されています。
FAQ
レンダリング時は変わりません。違いはブラウザに配信されるサイズにあります。next-intl は各ページで +12.6 KB gzip のランタイムを要し、一般的な構成では他のページのテキストの約90%を一緒に配信してしまいます。Next.js でのロケール切り替えとハイドレーション時間はほぼ同等です(15-18ミリ秒)。TanStack Start では use-intl が7-21ミリ秒かかるのに対し、Intlayer は3-4ミリ秒です。
はい、scoped-dynamic 構成を採用すれば可能です。messages/{locale}.json をルートごとのネームスペースに分割し、各ページで pick(messages, [...]) を適用し、コンポーネント移動時にもそのマッピングを正確に維持します。ベンチマークの scoped-* 行はその作業の成果を示しています。Intlayer はコンパイラがコンポーネントごとにコンテンツをスコープ化するため、何もしなくてもデフォルトで0%を達成します。バンドル最適化を参照してください。
いいえ。@intlayer/next-intl は useTranslations、getTranslations、useFormatter、t.rich()、ICU複数形、ナビゲーションヘルパーを維持し、コンパイル済み辞書から提供します。next.config.ts にプラグインを1行追加するだけです。詳細は next-intl 移行ガイド をご覧ください。
ネイティブAPIでのICUサポートは順次拡張中です。互換アダプター(@intlayer/next-intl、@intlayer/use-intl)はすでにICUを実行可能です。複数形、select、selectordinal、#、{ts, date, long} は Intlayer のICUリゾルバーを介して処理されます。詳しくは ICU メッセージ形式の解説 をお読みください。
はい。JSON同期プラグインがそれらを読み込み、トップレベルのキーを辞書に分割し、CLIやCMSの更新時に同じファイルへ翻訳を書き戻します。翻訳チームのワークフローを変える必要はありません。
関連する比較
同じベンチマーク、他のライブラリ:
next-intl についてさらに詳しく:
リファレンスドキュメント:
これらのライブラリがどのように生まれたのかを知るには、JavaScript i18n の歴史をご覧ください。
GitHub STARS
GitHub のスター数は、プロジェクトの人気、コミュニティの信頼、長期的な持続可能性を示す強力な指標です。技術的な品質を直接測るものではありませんが、どれだけ多くの開発者がそのプロジェクトを有用だと感じ、その進捗を追い、採用しているかを反映しています。
コミット数
スター数は人気を示し、コミット数はプロジェクトに注がれた作業量を示します。執筆時点で Intlayer のコミット数は約 7,500 件で、ここで比較している多くのライブラリを上回り、next-intl や next-i18next の約 5 倍です。
- amannn/next-intl
- aymericzip/intlayer
デフォルトブランチのコミット数、出典: GitHub API。
Intlayer はモノレポのため、この数には各フレームワーク向けパッケージ、CLI、ドキュメントがすべて含まれます。コミット数は品質ではなく活動量の指標として捉えてください。
npm ダウンロード数
- next-intl
- next-intlayer
出典: npm レジストリのダウンロード API。
ダウンロード数が評価するのは最良のソリューションではなく、最も古いソリューションです。何年も前に公開されたライブラリは、当時それを選んだすべてのプロジェクト、すべての CI 実行、それに依存するすべてのパッケージによって今もインストールされ続けます。この数値は新たな選択よりも惰性を表しています。
AI アシスタントはこの効果をさらに強めます。next-intl、i18next、vue-i18n は学習元のコードに大量に含まれているため、AI は代替手段を比較することなく、それらをデフォルトで提案します。提案のたびにダウンロード数が増え、それが次の提案を後押しします。ダウンロード数ではなく、ベンチマークで比較してください。
結論
next-intl は堅牢でよくメンテナンスされたライブラリであり、ベンチマーク結果からも Next.js における決して悪い選択肢ではないことが確認できます。しかし、中央集権型のカタログモデルは、あらゆる最適化の負担を開発者に課します。素朴な構成では他ページのコンテンツが約90%リークし、ランタイムだけでもすべてのページで +12.6 KB gzip のコストが発生します。
Intlayer はその作業をコンパイラに移行します。コンポーネントごとの辞書、ロケールごとの遅延読み込み、不要なコンテンツの削除は、慣習ではなくビルド出力です。同じアプリでの結果は、ページあたり +0.3 KB、リーク 0%、コンポーネントは 3分の1のサイズ、そして TanStack Start での言語切り替えは 2〜4倍高速 でした。
すべての生データ、テストアプリ、スクリプトは Benchmark Bloom リポジトリ で公開されています。ぜひご自身でお試しください。
詳細については、'Why Intlayer?' ドキュメント を参照してください。
コメント
まだコメントはありません。最初のコメントを共有しましょう。
