このページとあなたの好きなAIアシスタントを使ってドキュメントを要約します
Intlayer MCPサーバーを統合することで、ChatGPT、DeepSeek、Cursor、VSCodeなどから直接ドキュメントを取得できます。
MCPサーバーのドキュメントを表示このページのコンテンツはAIを使用して翻訳されました。
英語の元のコンテンツの最新バージョンを見るこのドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンクドキュメントのMarkdownをクリップボードにコピー
next-i18next VS next-intl VS intlayer | Next.jsの国際化(i18n)
Next.js向けの3つのi18nオプション、next-i18next、next-intl、Intlayerの類似点と相違点を見ていきましょう。
これは完全なチュートリアルではなく、選択の参考となる比較です。
私たちはNext.js 13+のApp Router(React Server Components対応)に焦点を当て、以下を評価します:
- アーキテクチャとコンテンツの構成
- TypeScriptと安全性
- 翻訳欠落の処理
- ルーティングとミドルウェア
- パフォーマンスと読み込み挙動
- 開発者体験(DX)、ツールとメンテナンス
- SEOと大規模プロジェクトの拡張性
要約: 3つのいずれもNext.jsアプリのローカライズが可能です。もしコンポーネント単位のコンテンツ管理、厳格なTypeScript型、ビルド時の欠落キー検出、ツリーシェイク可能な辞書、そして一流のApp Router + SEOヘルパーを求めるなら、Intlayerが最も完全でモダンな選択肢です。
開発者がよく混同しがちなのは、next-intlがreact-intlのNext.js版だと思うことです。そうではありません。next-intlはAmannによってメンテナンスされており、react-intlはFormatJSによってメンテナンスされています。
簡単に言うと
- next-intl - 軽量でシンプルなメッセージフォーマットを提供し、Next.jsのサポートがしっかりしています。カタログは中央集権的であることが多く、開発者体験(DX)はシンプルですが、安全性や大規模なメンテナンスは主にあなたの責任となります。
- next-i18next - Next.js向けにラップされたi18nextです。成熟したエコシステムとプラグイン(例:ICU)による機能を持ちますが、設定が冗長になりがちで、プロジェクトが大きくなるにつれてカタログは中央集権化しやすいです。
- Intlayer - Next.js向けのコンポーネント中心のコンテンツモデル、厳格なTS型付け、ビルド時チェック、ツリーシェイキング、組み込みのミドルウェア&SEOヘルパー、オプションのビジュアルエディター/CMS、およびAI支援翻訳。
バッジは自動的に更新されます。スナップショットは時間とともに変動します。
並列機能比較(Next.jsに特化)
| 機能 | next-intlayer (Intlayer) | next-intl | next-i18next |
バッジは自動的に更新されます。スナップショットは時間とともに変化します。
並列機能比較(Next.jsに特化)
機能 | next-intlayer (Intlayer) | next-intl | next-i18next |
---|---|---|---|
コンポーネント近くの翻訳 | ✅ はい、各コンポーネントにコンテンツが配置されています | ❌ いいえ | ❌ いいえ |
TypeScript 統合 | ✅ 高度、自動生成された厳密な型 | ✅ 良好 | ⚠️ 基本 |
翻訳漏れ検出 | ✅ TypeScript エラーのハイライトおよびビルド時のエラー/警告 | ⚠️ ランタイムフォールバック | ⚠️ ランタイムフォールバック |
リッチコンテンツ(JSX/Markdown/コンポーネント) | ✅ 直接サポート | ❌ リッチノード向けに設計されていません | ⚠️ 制限あり |
AI搭載翻訳 | ✅ はい、複数のAIプロバイダーをサポート。独自のAPIキーを使用可能。アプリケーションのコンテキストとコンテンツの範囲を考慮します | ❌ いいえ | ❌ いいえ |
ビジュアルエディター | ✅ はい、ローカルのビジュアルエディター+オプションのCMS;コードベースのコンテンツを外部化可能;埋め込み可能 | ❌ いいえ/外部のローカリゼーションプラットフォーム経由で利用可能 | ❌ いいえ/外部のローカリゼーションプラットフォーム経由で利用可能 |
ローカライズされたルーティング | ✅ はい、標準でローカライズされたパスをサポート(Next.js & Viteで動作) | ✅ 組み込み、App Routerは[locale]セグメントをサポート | ✅ 組み込み |
動的ルート生成 | ✅ はい | ✅ はい | ✅ はい |
複数形対応 | ✅ 列挙ベースのパターン | ✅ 良好 | ✅ 良好 |
フォーマット(日時、数値、通貨) | ✅ 最適化されたフォーマッター(内部でIntlを使用) | ✅ 良好(Intlヘルパー) | ✅ 良好(Intlヘルパー) |
コンテンツフォーマット | ✅ .tsx、.ts、.js、.json、.md、.txt、(.yaml 開発中) | ✅ .json、.js、.ts | ⚠️ .json |
ICUサポート | ⚠️ 作業中 | ✅ あり | ⚠️ プラグイン経由(i18next-icu) |
SEOヘルパー(hreflang、サイトマップ) | ✅ 組み込みツール:サイトマップ、robots.txt、メタデータのヘルパー | ✅ 良好 | ✅ 良好 |
エコシステム / コミュニティ | ⚠️ 小規模だが急速に成長し、反応が良い | ✅ 良好 | ✅ 良好 |
サーバーサイドレンダリング & サーバーコンポーネント | ✅ はい、SSR / Reactサーバーコンポーネント向けに最適化 | ⚠️ ページレベルでサポートされているが、子のサーバーコンポーネントに対してt関数をコンポーネントツリーに渡す必要がある | ⚠️ ページレベルでサポートされているが、子のサーバーコンポーネントに対してt関数をコンポーネントツリーに渡す必要がある |
ツリーシェイキング(使用されたコンテンツのみを読み込む) | ✅ はい、Babel/SWCプラグインを使用したビルド時のコンポーネント単位で対応 | ⚠️ 部分的に対応 | ⚠️ 部分的に対応 |
遅延読み込み | ✅ はい、ロケール単位 / 辞書単位で対応 | ✅ はい(ルート単位/ロケール単位)、名前空間管理が必要 | ✅ はい(ルート単位/ロケール単位)、名前空間管理が必要 |
未使用コンテンツの削除 | ✅ はい、ビルド時に辞書単位で対応 | ❌ いいえ、名前空間管理で手動対応可能 | ❌ いいえ、名前空間管理で手動対応可能 |
大規模プロジェクトの管理 | ✅ モジュール化を推奨し、デザインシステムに適している | ✅ セットアップによるモジュール化対応 | ✅ セットアップによるモジュール化対応 |
翻訳漏れのテスト(CLI/CI) | ✅ CLI: npx intlayer content test(CIに適した監査) | ⚠️ 組み込みではない;ドキュメントでは npx @lingual/i18n-check を推奨 | ⚠️ 組み込みではない;i18nextツールやランタイムの saveMissing に依存 |
はじめに
Next.jsは国際化されたルーティング(例:ロケールセグメント)を組み込みでサポートしています。しかし、その機能だけでは翻訳は行われません。ユーザーにローカライズされたコンテンツを表示するには、別途ライブラリが必要です。
多くのi18nライブラリが存在しますが、Next.jsの世界では現在、next-i18next、next-intl、そしてIntlayerの3つが注目されています。
アーキテクチャとスケーラビリティ
- next-intl / next-i18next: ロケールごとに 集中管理されたカタログ(および i18next の場合は ネームスペース)をデフォルトとします。初期段階では問題なく機能しますが、結合度が高まりキーの変更が頻繁になると、大きな共有領域となってしまいます。
- Intlayer: サービスするコードと 共置 された コンポーネント単位(または機能単位)の辞書を推奨します。これにより認知負荷が軽減され、UIパーツの重複や移行が容易になり、チーム間の競合も減少します。未使用のコンテンツも自然に見つけやすく削除しやすくなります。
なぜ重要か: 大規模なコードベースやデザインシステムのセットアップでは、モジュール化されたコンテンツの方がモノリシックなカタログよりもスケールしやすいです。
バンドルサイズと依存関係
アプリケーションをビルドした後、バンドルとはブラウザがページをレンダリングするために読み込むJavaScriptのことです。したがって、バンドルサイズはアプリケーションのパフォーマンスにとって重要です。
多言語アプリケーションのバンドルにおいて重要な2つの要素は以下の通りです:
- アプリケーションコード
- ブラウザによって読み込まれるコンテンツ
アプリケーションコード
この場合、アプリケーションコードの重要性は最小限です。3つのソリューションすべてがツリーシェイカブルであり、未使用のコード部分はバンドルに含まれません。
以下は、3つのソリューションを用いた多言語アプリケーションでブラウザが読み込むJavaScriptバンドルサイズの比較です。
アプリケーション内でフォーマッターを必要としない場合、ツリーシェイキング後にエクスポートされる関数のリストは以下のようになります:
- next-intlayer: useIntlayer, useLocale, NextIntlClientProvider、(バンドルサイズは180.6 kB -> 78.6 kB(gzip))
- next-intl: useTranslations, useLocale, NextIntlClientProvider、(バンドルサイズは101.3 kB -> 31.4 kB(gzip))
- next-i18next: useTranslation, useI18n, I18nextProvider、(バンドルサイズは80.7 kB -> 25.5 kB(gzip))
これらの関数はReactのコンテキスト/ステートのラッパーに過ぎないため、i18nライブラリがバンドルサイズに与える影響は最小限です。
Intlayerは、useIntlayer関数により多くのロジックを含んでいるため、next-intlやnext-i18nextよりわずかに大きくなっています。これはマークダウンやintlayer-editorの統合に関連しています。
コンテンツと翻訳
この部分は開発者によってしばしば無視されますが、10ページで構成され、10言語に対応したアプリケーションの場合を考えてみましょう。計算を簡単にするために、各ページが100%ユニークなコンテンツを統合していると仮定します(実際には、ページタイトル、ヘッダー、フッターなど、ページ間で重複するコンテンツが多くあります)。
/fr/about ページを訪れたいユーザーは、特定の言語で1ページ分のコンテンツを読み込みます。コンテンツの最適化を無視すると、アプリケーションのコンテンツの8,200% ((1 + (((10ページ - 1) × (10言語 - 1)))) × 100) を不必要に読み込むことになります。この問題がわかりますか?このコンテンツがテキストのままであっても、おそらくサイトの画像の最適化を考える方が多いでしょうが、無駄なコンテンツを世界中に送信し、ユーザーのコンピューターに無意味な処理をさせているのです。
2つの重要な問題:
ルートによる分割:
/about ページにいる場合、/home ページのコンテンツを読み込みたくない
ロケールによる分割:
/fr/about ページにいる場合、/en/about ページのコンテンツを読み込みたくない
改めて、これら3つのソリューションはこれらの問題を認識しており、これらの最適化を管理することができます。3つのソリューションの違いはDX(開発者体験)にあります。
next-intl と next-i18next は翻訳を管理するために集中管理型のアプローチを使用しており、ロケールやサブファイルごとにJSONを分割することが可能です。next-i18next ではJSONファイルを「ネームスペース」と呼び、next-intl ではメッセージを宣言することができます。intlayer ではJSONファイルを「辞書」と呼びます。
- next-intlの場合は、next-i18nextと同様に、コンテンツはページやレイアウトレベルで読み込まれ、その後このコンテンツがコンテキストプロバイダーに読み込まれます。つまり、開発者は各ページで読み込まれるJSONファイルを手動で管理する必要があります。
実際には、開発者はこの最適化を省略し、単純さのためにページのコンテキストプロバイダーにすべてのコンテンツを読み込むことを好むことが多いです。
- intlayerの場合は、すべてのコンテンツがアプリケーション内で読み込まれます。その後、プラグイン(@intlayer/babel / @intlayer/swc)がバンドルを最適化し、ページで使用されるコンテンツのみを読み込みます。したがって、開発者は読み込まれる辞書を手動で管理する必要がありません。これにより、より良い最適化、より良い保守性、そして開発時間の短縮が可能になります。
アプリケーションが成長するにつれて(特に複数の開発者がアプリケーションに関わっている場合)、JSONファイルからもはや使用されていないコンテンツを削除し忘れることがよくあります。
すべてのJSONはすべての場合に読み込まれることに注意してください(next-intl、next-i18next、intlayer)。
これがIntlayerのアプローチがよりパフォーマンスに優れている理由です。コンポーネントがもはや使用されていない場合、その辞書はバンドルに読み込まれません。
ライブラリがフォールバックをどのように処理するかも重要です。アプリケーションがデフォルトで英語であり、ユーザーが/fr/aboutページを訪れたとします。フランス語の翻訳が欠けている場合、英語のフォールバックが考慮されます。
next-intl と next-i18next の場合、ライブラリは現在のロケールに関連する JSON に加えて、フォールバックロケールの JSON も読み込む必要があります。したがって、すべてのコンテンツが翻訳されていると仮定すると、各ページは 100% 不要なコンテンツを読み込むことになります。これに対して、intlayer は辞書のビルド時にフォールバックを処理します。したがって、各ページは使用されるコンテンツのみを読み込みます。
以下は、vite + react アプリケーションで intlayer を使用したバンドルサイズ最適化の影響の例です:
最適化されたバンドル | 最適化されていないバンドル |
---|---|
![]() | ![]() |
TypeScript と安全性
next-intl
- 安定した TypeScript サポートを提供しますが、キーはデフォルトで厳密に型付けされていません。安全性のパターンは手動で維持する必要があります。
next-i18next
- フックの基本的な型定義がありますが、厳密なキーの型付けには追加のツールや設定が必要です。
intlayer
- コンテンツから厳密な型を生成します。IDEのオートコンプリートやコンパイル時エラーにより、デプロイ前にタイプミスやキーの欠落を検出します。
なぜ重要か: 強い型付けにより、失敗を右(実行時)ではなく左(CI/ビルド時)にシフトさせます。
翻訳欠落の取り扱い
next-intl
- 実行時のフォールバックに依存(例:キーやデフォルトロケールを表示)。ビルドは失敗しません。
next-i18next
- 実行時のフォールバックに依存(例:キーやデフォルトロケールを表示)。ビルドは失敗しません。
intlayer
- ビルド時検出により、ロケールやキーの欠落に対して警告/エラーを出します。
なぜ重要か: ビルド時に欠落を検出することで、本番環境での「謎の文字列」発生を防ぎ、厳格なリリースゲートに適合します。
ルーティング、ミドルウェア & URL戦略
next-intl
- App Router上のNext.jsのローカライズされたルーティングに対応。
next-i18next
- App Router上のNext.jsのローカライズされたルーティングに対応。
intlayer
- 上記すべてに加え、i18nミドルウェア(ヘッダーやクッキーによるロケール検出)およびローカライズされたURLや<link rel="alternate" hreflang="…">タグを生成するヘルパーを提供。
重要な理由: カスタムの接着層が減り、一貫したUXとクリーンなSEOをロケール間で実現。
サーバーコンポーネント(RSC)対応
next-intl
- Next.js 13+をサポート。ハイブリッド構成では、t関数やフォーマッターをコンポーネントツリーに渡すことが多い。
next-i18next
- Next.js 13+ をサポート。翻訳ユーティリティを境界を越えて渡す際に類似の制約があります。
intlayer
- Next.js 13+ をサポートし、一貫した API と RSC 指向のプロバイダーで サーバー/クライアントの境界 をスムーズにし、フォーマッターや t-関数のやり取りを回避します。
重要な理由: ハイブリッドツリーにおけるメンタルモデルがより明確になり、エッジケースが減少します。
DX、ツール&メンテナンス
next-intl
- 外部のローカリゼーションプラットフォームや編集ワークフローと組み合わせて使われることが多いです。
next-i18next
- 外部のローカリゼーションプラットフォームや編集ワークフローと組み合わせて使われることが多いです。
intlayer
- 無料のビジュアルエディターとオプションのCMS(Git対応または外部化可能)を提供し、さらにVSCode拡張機能と、独自のプロバイダーキーを使用したAI支援翻訳も備えています。
重要な理由: 運用コストを削減し、開発者とコンテンツ作成者間のフィードバックループを短縮します。
ローカリゼーションプラットフォーム(TMS)との統合
大規模な組織では、Crowdin、Phrase、Lokalise、Localizely、Localazyなどの翻訳管理システム(TMS)に依存することが多いです。
企業が重視する理由
- 協力と役割分担:複数の関係者が関与します。開発者、プロダクトマネージャー、翻訳者、レビュアー、マーケティングチームなど。
- 規模と効率性:継続的なローカリゼーション、コンテキスト内レビュー。
next-intl / next-i18next
- 通常は集中管理されたJSONカタログを使用するため、TMSとのエクスポート/インポートが簡単です。
- 上記プラットフォーム向けの成熟したエコシステムや例/統合があります。
Intlayer
- 分散型のコンポーネントごとの辞書を推奨し、TypeScript/TSX/JS/JSON/MDコンテンツをサポートします。
- これによりコードのモジュール性が向上しますが、ツールが集中管理されたフラットなJSONファイルを期待する場合、プラグアンドプレイのTMS統合が難しくなることがあります。
- Intlayerは代替手段を提供します:AI支援翻訳(ご自身のプロバイダーキーを使用)、ビジュアルエディター/CMS、およびギャップを検出して事前入力するためのCLI/CIワークフロー。
注意: next-intl と i18next は TypeScript カタログも受け入れます。もしチームがメッセージを .ts ファイルに保存したり、機能ごとに分散管理している場合、同様の TMS の摩擦に直面することがあります。しかし、多くの next-intl のセットアップは locales/ フォルダに集中しており、TMS 用に JSON にリファクタリングするのが少し容易です。
開発者体験
この部分では、3つのソリューションを深く比較します。各ソリューションの「はじめに」ドキュメントに記載されている単純なケースを考慮するのではなく、より実際のプロジェクトに近い実用的なユースケースを考えます。
アプリ構造
アプリの構造は、コードベースの良好な保守性を確保するために重要です。
.├── locales│ ├── en│ │ ├── home.json│ │ └── navbar.json│ ├── fr│ │ ├── home.json│ │ └── navbar.json│ └── es│ ├── home.json│ └── navbar.json├── i18n.ts└── src ├── middleware.ts ├── app │ └── home.tsx └── components └── Navbar └── index.tsx
比較
- next-intl / next-i18next: 集中管理されたカタログ(JSON; 名前空間/メッセージ)。構造が明確で翻訳プラットフォームとよく統合されるが、アプリが大きくなるとファイル間の編集が増える可能性がある。
- Intlayer: コンポーネントごとに .content.{ts|js|json} 辞書がコンポーネントと同じ場所に配置されている。コンポーネントの再利用や局所的な理解が容易になるが、ファイルが増え、ビルド時のツールに依存する。
セットアップとコンテンツの読み込み
前述のように、各JSONファイルのインポート方法を最適化する必要があります。
ライブラリがコンテンツの読み込みをどのように処理するかが重要です。
コードをクリップボードにコピー
import { getRequestConfig } from "next-intl/server";import { notFound } from "next/navigation";// 共有設定からインポート可能const locales = ["en", "fr", "es"];export default getRequestConfig(async ({ locale }) => { // 受け取った `locale` パラメータが有効か検証します if (!locales.includes(locale as any)) notFound(); return { messages: (await import(`../messages/${locale}.json`)).default, };});
コードをクリップボードにコピー
import { NextIntlClientProvider } from "next-intl";import { getMessages, unstable_setRequestLocale } from "next-intl/server";import pick from "lodash/pick";export default async function LocaleLayout({ children, params,}: { children: React.ReactNode; params: { locale: string };}) { const { locale } = params; // このサーバーレンダリング(RSC)用にアクティブなリクエストロケールを設定します unstable_setRequestLocale(locale); // メッセージは src/i18n/request.ts 経由でサーバー側で読み込まれます // (next-intl のドキュメント参照)。ここではクライアントコンポーネントに必要な // サブセットのみをクライアントに渡します(ペイロード最適化)。 const messages = await getMessages(); const clientMessages = pick(messages, ["common", "about"]); return ( <html lang={locale}> <body> <NextIntlClientProvider locale={locale} messages={clientMessages}> {children} </NextIntlClientProvider> </body> </html> );}
コードをクリップボードにコピー
import { getTranslations } from "next-intl/server";import { ClientComponent, ServerComponent } from "@components";export default async function LandingPage({ params,}: { params: { locale: string };}) { // 完全にサーバー側での読み込み(クライアント側でのハイドレーションなし) const t = await getTranslations("about"); return ( <main> <h1>{t("title")}</h1> <ClientComponent /> <ServerComponent /> </main> );}
比較
3つすべてがロケールごとのコンテンツ読み込みとプロバイダーをサポートしています。
next-intl/next-i18next では、通常、ルートごとに選択されたメッセージや名前空間を読み込み、必要な場所にプロバイダーを配置します。
Intlayer では、ビルド時の解析を追加して使用状況を推測し、手動の配線を減らし、単一のルートプロバイダーを許可する場合があります。
チームの好みに応じて、明示的な制御と自動化のどちらかを選択してください。
クライアントコンポーネントでの使用例
カウンターをレンダリングするクライアントコンポーネントの例を見てみましょう。
翻訳(形状は再利用可能;お好みで next-intl のメッセージにロードしてください)
コードをクリップボードにコピー
{ "counter": { "label": "Counter", "increment": "Increment" }}
コードをクリップボードにコピー
{ "counter": { "label": "Compteur", "increment": "Incrémenter" }}
クライアントコンポーネント
コードをクリップボードにコピー
"use client";import React, { useState } from "react";import { useTranslations, useFormatter } from "next-intl";const ClientComponentExample = () => { // ネストされたオブジェクトに直接スコープを設定 const t = useTranslations("about.counter"); const format = useFormatter(); const [count, setCount] = useState(0); return ( <div> <p>{format.number(count)}</p> <button aria-label={t("label")} onClick={() => setCount((count) => count + 1)} > {t("increment")} </button> </div> );};
ページのクライアントメッセージに "about" メッセージを追加するのを忘れないでください
比較
数値フォーマット
- next-i18next: useNumber はなく、Intl.NumberFormat(または i18next-icu)を使用。
- next-intl: useFormatter().number(value) を使用。
- Intlayer: 組み込みの useNumber() を使用。
キー
- ネストされた構造(about.counter.label)を維持し、フックのスコープを適切に設定する(useTranslation("about") + t("counter.label") または useTranslations("about.counter") + t("label"))。
ファイルの場所
- next-i18next は public/locales/{lng}/{ns}.json に JSON を期待。
- next-intl は柔軟で、設定に応じてメッセージをロード可能。
- Intlayer は TS/JS の辞書にコンテンツを格納し、キーで解決。
サーバーコンポーネントでの使用
UIコンポーネントの場合を考えます。このコンポーネントはサーバーコンポーネントであり、クライアントコンポーネントの子として挿入できる必要があります。(ページ(サーバーコンポーネント) -> クライアントコンポーネント -> サーバーコンポーネント)。このコンポーネントはクライアントコンポーネントの子として挿入できるため、非同期にはできません。
コードをクリップボードにコピー
type ServerComponentProps = { count: number; t: (key: string) => string;};const ServerComponent = ({ t, count }: ServerComponentProps) => { const formatted = new Intl.NumberFormat(i18n.language).format(count); return ( <div> <p>{formatted}</p> <button aria-label={t("label")}>{t("increment")}</button> </div> );};
サーバーコンポーネントは非同期にできないため、翻訳関数とフォーマッター関数をプロパティとして渡す必要があります。
- const t = await getTranslations("about.counter");
- const format = await getFormatter();
Intlayerはnext-intlayer/serverを通じてサーバーセーフなフックを提供します。動作するために、useIntlayerとuseNumberはクライアントフックに似たフックのような構文を使用しますが、内部的にはサーバーコンテキスト(IntlayerServerProvider)に依存しています。
メタデータ / サイトマップ / ロボット
コンテンツの翻訳は素晴らしいことです。しかし、多くの人は国際化の主な目的があなたのウェブサイトを世界により見えるようにすることだということを忘れがちです。I18nはあなたのウェブサイトの可視性を向上させるための非常に強力な手段です。
以下は多言語SEOに関するベストプラクティスのリストです。
- <head>タグ内にhreflangメタタグを設定する > これは検索エンジンがページで利用可能な言語を理解するのに役立ちます
- sitemap.xml にすべてのページの翻訳を http://www.w3.org/1999/xhtml XML スキーマを使ってリストアップする >
- robots.txt からプレフィックス付きページを除外するのを忘れない(例:/dashboard、および /fr/dashboard、/es/dashboard) >
- カスタム Link コンポーネントを使って最もローカライズされたページへリダイレクトする(例:フランス語では <a href="/fr/about">A propos</a>) >
開発者はしばしばロケール間でページを適切に参照することを忘れがちです。
コードをクリップボードにコピー
import type { Metadata } from "next";import { locales, defaultLocale } from "@/i18n";import { getTranslations } from "next-intl/server";function localizedPath(locale: string, path: string) { return locale === defaultLocale ? path : "/" + locale + path;}export async function generateMetadata({ params,}: { params: { locale: string };}): Promise<Metadata> { const { locale } = params; const t = await getTranslations({ locale, namespace: "about" }); const url = "/about"; const languages = Object.fromEntries( locales.map((locale) => [locale, localizedPath(locale, url)]) ); return { title: t("title"), description: t("description"), alternates: { canonical: localizedPath(locale, url), languages: { ...languages, "x-default": url }, }, };}// ... ページの残りのコード
コードをクリップボードにコピー
import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const formatterLocalizedPath = (locale: string, path: string) => locale === defaultLocale ? origin + path : origin + "/" + locale + path;export default function sitemap(): MetadataRoute.Sitemap { const aboutLanguages = Object.fromEntries( locales.map((l) => [l, formatterLocalizedPath(l, "/about")]) ); return [ { url: formatterLocalizedPath(defaultLocale, "/about"), lastModified: new Date(), changeFrequency: "monthly", priority: 0.7, alternates: { languages: aboutLanguages }, }, ];}
コードをクリップボードにコピー
import type { MetadataRoute } from "next";import { locales, defaultLocale } from "@/i18n";const origin = "https://example.com";const withAllLocales = (path: string) => [ path, ...locales .filter((locale) => locale !== defaultLocale) .map((locale) => "/" + locale + path),];export default function robots(): MetadataRoute.Robots { const disallow = [ ...withAllLocales("/dashboard"), ...withAllLocales("/admin"), ]; return { rules: { userAgent: "*", allow: ["/"], disallow }, host: origin, sitemap: origin + "/sitemap.xml", };}
Intlayerは、サイトマップ用の多言語URLを生成するためのgetMultilingualUrls関数を提供しています。
そして勝者は…
簡単ではありません。各オプションにはトレードオフがあります。私の見解は以下の通りです:
next-intl
- 最もシンプルで軽量、強制される決定が少ないです。最小限のソリューションを求めていて、集中管理されたカタログに慣れており、アプリが小規模から中規模の場合に適しています。
next-i18next
- 成熟しており、機能が豊富でコミュニティプラグインも多いですが、セットアップコストは高めです。i18nextのプラグインエコシステム(例:プラグイン経由の高度なICUルール)が必要で、チームがすでにi18nextを知っていて、柔軟性のためにより多くの設定を受け入れられる場合に適しています。
Intlayer
- モダンな Next.js 向けに構築されており、モジュラーコンテンツ、型安全性、ツール群、そしてボイラープレートの削減を実現しています。コンポーネント単位のコンテンツ管理、厳格な TypeScript、ビルド時の保証、ツリーシェイキング、そしてルーティング/SEO/エディターツールがバッテリー込みで提供されることを重視する場合、特に Next.js App Router、デザインシステム、そして大規模でモジュラーなコードベースに最適です。
セットアップを最小限に抑え、多少の手動設定を許容できるなら next-intl が良い選択です。すべての機能が必要で複雑さを気にしないなら next-i18next が適しています。しかし、モダンでスケーラブル、モジュラーなソリューションをビルトインツールと共に求めるなら、Intlayer はそれをすぐに提供することを目指しています。
エンタープライズチーム向けの代替案: Crowdin、Phrase、またはその他のプロフェッショナルな翻訳管理システムのような確立されたローカリゼーションプラットフォームと完全に連携する、実績のあるソリューションが必要な場合は、成熟したエコシステムと実証済みの統合を持つ next-intl または next-i18next を検討してください。
今後のロードマップ: Intlayer は、i18next および next-intl ソリューションの上に動作するプラグインの開発も計画しています。これにより、Intlayer の自動化、構文、およびコンテンツ管理の利点を享受しつつ、これらの確立されたソリューションがアプリケーションコードに提供するセキュリティと安定性を維持できます。
GitHub STARs
GitHubのスターは、プロジェクトの人気、コミュニティの信頼、そして長期的な関連性を示す強力な指標です。技術的な品質の直接的な尺度ではありませんが、どれだけ多くの開発者がそのプロジェクトを有用と感じ、進捗を追い、採用する可能性が高いかを反映しています。プロジェクトの価値を評価する際、スターは代替案間のトラクションを比較し、エコシステムの成長に関する洞察を提供するのに役立ちます。
結論
3つのライブラリはすべてコアなローカリゼーションに成功しています。違いは、モダンな Next.js で堅牢でスケーラブルなセットアップを実現するために、どれだけの作業が必要かという点です。
- Intlayer では、モジュラーコンテンツ、厳格なTS、ビルド時の安全性、ツリーシェイクされたバンドル、および 一流のApp Router + SEOツール が デフォルト であり、手間ではありません。
- チームが多言語対応のコンポーネント駆動型アプリにおいて、保守性と速度を重視するなら、Intlayerは今日最も完全な体験を提供します。
詳細は 'Why Intlayer?' ドキュメント を参照してください。