Lingvit
  • Next.js
  • i18n
  • ガイド

Next.jsの国際化:i18n設定 vs 自動翻訳(2026年版)

読了時間 9分

Next.jsは多言語アプリへの根本的に異なる2つの道を用意しています。組み込みのi18nルーティングを翻訳ライブラリと組み合わせる方法と、DOMベースの自動翻訳をスクリプトタグ1つで使う方法です。このガイドでは 両方を解説します — それぞれが実際に何をするのか、何がコストになるのか、そしてどちらを 選ぶべきか。

Next.jsのi18nルーティング:得られるもの

Next.jsには、next.config.tsで 設定する組み込みのi18nルーティング層があります。これが扱うのは2つのことです:URL ルーティング(/fr/、 /de/プレフィックス)と、 Accept-Languageヘッダーによる ブラウザのロケール検出です。

これが行わないことは、コンテンツの翻訳です。i18nルーティング設定は 純粋にインフラであり、URL構造とロケール検出を整えるだけで、あとは他に委ねます。 コンポーネント内の実際の翻訳済みテキストのためには、その上に翻訳ライブラリを 追加する必要があります:next-intl、react-i18next、 あるいはLinguiJSです。

ルーティング設定だけでも、 yourapp.com/fr/dashboardへの アクセスが独立したURLとして機能することを意味し、SEOや共有可能なリンクに有用ですが、 翻訳ライブラリがなければページは依然として英語でレンダリングされます。

Next.js向けの完全なi18nスタック

next-intlを使った完全なNext.js i18nセットアップには、次の要素が 含まれます。

  1. 対応ロケールとデフォルトを宣言する next.config.tsのi18nブロック。
  2. ロケールごとのJSONメッセージファイル: messages/en.json、 messages/fr.jsonなどで、 リポジトリにコミットされ新しいUI文字列のたびに更新されます。
  3. 英語のソースファイルから生成される型安全なメッセージキーで、TypeScriptがコンパイル時に 欠落や誤記のキーを検出します。
  4. Server ComponentsはgetTranslations()で メッセージを読み込み、Client Componentsは <NextIntlClientProvider>で ラップされます。
  5. RTL言語(アラビア語、ヘブライ語)には別途CSS作業が必要です:ルート要素への dir="rtl"設定、 論理プロパティのユーティリティ、アイコンの反転などです。

最小限のnext.config.tsi18n ブロックの例:

const nextConfig = {
  i18n: {
    locales: ["en", "fr", "de", "es"],
    defaultLocale: "en",
  },
};
export default nextConfig;

対応するmessages/en.json:

{
  "nav": {
    "home": "Home",
    "pricing": "Pricing",
    "docs": "Documentation"
  },
  "hero": {
    "headline": "Add languages to your app",
    "cta": "Get started free"
  }
}

en.json内のすべてのキーは、 他のすべてのロケールファイルにも複製され、翻訳され、製品の進化に合わせて同期を 保たれる必要があります。

大規模時のコスト

t()でラップする単位あたりの コストはわずかです。累積すると急速にコストが積み上がります。

コンテンツとコードの結合

新しいUI文字列にはすべて、ソースファイルへの新しいキーと、各対象ロケールファイルへの 対応するエントリが必要です。月曜日に出荷された新機能は、フランス語とドイツ語のユーザーが キーのフォールバック以外の何かを目にする前に、両ファイルの更新が必要であることを 意味します。

言語ごとの複数形ルール

英語には2つの複数形があります。アラビア語には6つ。ポーランド語には複雑なルールを 持つ4つがあります。ICUメッセージ形式がこれを処理しますが、複数形の文字列は すべてロケールごとに個別の定義が必要です — 単一の文字列にカウントを含める素朴な アプローチは多くの言語で破綻します。

動的な値の埋め込み

“Welcome, {name}!”や“You have {count} items”のような 文字列には、ライブラリごとに異なる埋め込み構文が必要で、すべてのロケールで テストが必要であり、英語と語順が異なる言語では文法的に誤った出力を生む 可能性があります。

TypeScriptのオーバーヘッド

型安全なキーには、英語のソースから生成される型ファイルが必要です。この生成 ステップはCIで実行する必要があり、ビルド時間を押し上げ、ソースロケールファイルに 構造的な問題があるとビルドが失敗します — 有用ですが無料ではありません。

RTLは別プロジェクト

next-intlとreact-i18nextはテキストを翻訳しますが、レイアウトの方向は反転しません。 アラビア語やヘブライ語のサポートには別途作業が必要です: dir="rtl"の設定、 すべてのコンポーネントの物理的CSSプロパティの監査( margin-left→ margin-inline-start)、 そしてRTLモードでのレイアウト全体のテストです。

Next.jsのi18n設定が正しい選択となる場面

完全なライブラリスタックが妥当、または必須となる具体的な文脈があります。

  • コミュニティによる翻訳があるオープンソースアプリ

    GitHub上でコミュニティが翻訳を提供する場合(JSONやPOファイルとして)、 標準的なライブラリ形式が正しいコントリビューター向けインターフェースです。 自動翻訳はこのモデルには対応しません。

  • コンプライアンスが求められるコンテンツ

    規制業界(法律、医療、金融)では、すべてのUI文字列が明示的にレビュー・承認 される必要がある場合があります。i18nライブラリは、すべての文字列を バージョン履歴を持つ監査可能な独立した成果物にします。

  • 大量の数値・日付・通貨フォーマット

    UI全体で数値、日付、通貨をフォーマットするアナリティクスダッシュボードや 会計ツールは、FormatJSやnext-intlが標準提供するロケール対応の IntlAPI連携から 恩恵を受けます。

  • オフライン対応アプリ

    完全なオフラインサポートを持つPWAは、オフライン時に翻訳APIを呼び出せないため、 ビルド時にバンドルされた翻訳ファイルが必要です。ライブラリベースのi18nが 唯一の選択肢です。

自動翻訳:Next.jsでの仕組み

代替手段は、ルートのapp/layout.tsx内、 <body>要素の中に置く スクリプトタグです。next.config.tsの 変更も、ロケールルーティングの設定も、JSONファイルも不要です。

このスクリプトはMutationObserverを使い、Next.jsがレンダリングした後の DOMを監視します。これにより以下が処理されます。

  • 初期のServer Component HTML — サーバーでレンダリングされブラウザにストリームされる ページコンテンツ。
  • ハイドレーション後のコンテンツ — Client Componentの状態変化、 useEffect由来のデータ、 遅延読み込みされるコンポーネント。
  • クライアントサイドナビゲーション — Next.jsのルート遷移は、新しくレンダリングされた ページコンテンツに対してオブザーバーを発火させます。
  • RTLレイアウト — アラビア語、ヘブライ語、その他のRTL言語に切り替えると document.documentElement.dirが 自動的に設定されます。

このアプローチはApp RouterとPages Routerの両方で動作します。レンダリングモデル (サーバーかクライアントか)は関係なく、最終的なDOM出力だけが重要です。

セットアップ比較

セットアップの複雑さの差は歴然です。next-intlの道筋とLingvitのスクリプトタグの 道筋を比較します。

next-intlのセットアップ(約8ファイル、約200行の設定)

# 作成または変更するファイル
next.config.ts          ← i18nブロックを追加
middleware.ts           ← ロケール検出 + リダイレクト
i18n/request.ts         ← ロケール解決ヘルパー
i18n/routing.ts         ← 型付きルート定義
app/[locale]/layout.tsx ← NextIntlClientProviderラッパー
messages/en.json        ← ソース文字列
messages/fr.json        ← フランス語翻訳
messages/de.json        ← ドイツ語翻訳
# … 追加言語ごとに1ファイル

Lingvitのセットアップ(1行)

// app/layout.tsx — <body>内に追加
<script src="https://cdn.lingvit.com/widget/v1/widget.bundle.js"
  data-project-id="YOUR_PROJECT_ID"
  async />

// これだけです。next.config.tsの変更もJSONファイルも不要。

自動翻訳がカバーしないもの

DOMベースの翻訳には、選ぶ前に理解しておくべき現実的な制約があります。

サーバーサイドのメール文字列

サーバーコード内の文字列定数から組み立てられるトランザクションメールは、 ブラウザのDOMには一切レンダリングされません。多言語メールテンプレートシステムや ロケールごとのメールテンプレートといった別途の翻訳対応が必要です。

DOMにレンダリングされない文字列

ロギング専用のハードコードされた文字列、ブラウザ以外のクライアントが消費する APIレスポンス、サーバーサイドでのみ処理されるコンテンツはMutationObserverから 見えず、翻訳されません。

複雑なICU複数形処理

動的にカウントされる値について、アラビア語(6つの複数形)やポーランド語 (例外ルールを持つ4つの形)で文法的に正しい複数形処理が必要なアプリケーションには ICUメッセージフォーマットのサポートが必要です — これはライブラリの機能であり、 DOMレベルの翻訳が自動的に処理するものではありません。

よくある質問

LingvitはApp RouterのServer Componentsで動作しますか?

はい。Server Componentsは、ブラウザが受け取り他のHTMLと全く同じようにDOMに挿入されるHTMLを生成します。Lingvitのスクリプトはこのコンテンツを通常通りMutationObserver経由で検知します。Server Component専用の特別な処理は必要ありません。

next-intlと併用できますか?

はい。一部の文字列にnext-intlを使い、残りに自動翻訳を使いたい場合、両方を共存させられます。Lingvitはレンダリング時にDOM内にあるテキストノードをすべて翻訳します。next-intlでレンダリングされた文字列がロケールファイル内でまだ翻訳されていない場合も対象になります。

SEOについて — 自動翻訳はインデックス可能な言語URLを作成しますか?

いいえ、一般的なローンチ機能としては作成しません。独立してインデックス可能な言語ページには、Next.jsのロケールルーティングとサーバーレンダリングされたメタデータを使ってください。Lingvitはブラウザ内での対応するランタイム翻訳を処理します。