Next。js Web サイトを翻訳するには 2 つの方法があります。の コードルート: すべてのルートを の下に置きます app/[lang] セグメントで訪問者の言語を検出します proxy.js、 ロケールごとに翻訳辞書をロードし、 で hreflang タグを出力します alternates メタデータフィールド。の ノーコードルート: 翻訳サービスのスクリプトをルート レイアウトに追加し、SEO 用のサブディレクトリまたはサブドメインから提供される翻訳 URL を使用して、レンダリングされたページを翻訳できるようにします。
コード ルートを使用すると、テキストがコードベース内に存在し、開発者がそれを維持している場合に完全に制御でき、最も効果的に機能します。テキストが CMS から取得される場合、開発者以外の人が翻訳を編集する必要がある場合、または一度に多くの言語が必要な場合、ノーコード ルートの方が高速になります。このガイドは、Next。js 16 のドキュメントに基づいて両方を示し、いずれにしても多言語 SEO のチェックリストで終わります。
主なポイント
- アプリルーター: 下部にネストページ
app/[lang]、 リダイレクトインproxy.js(と呼ばれるmiddleware.jsNext。js 16)の前に、サーバーコンポーネントにJSON辞書をロードし、ロケールをプレレンダリングしますgenerateStaticParams. - ページルーター: 内蔵を使用します
i18n設定するnext.config.js。動作しませんoutput: 'export'. - Next。js は hreflang を追加しません。App Routerでは、 を使用します
alternates.languagesでgenerateMetadata. - ノーコードオプションは1 つです
<Script>タグインapp/layout.tsx。インデックス可能な翻訳ページの場合は、ブラウザのみでの翻訳ではなく、サブディレクトリまたはサブドメインのセットアップを使用してください。 - どのルートを選択しても、設定します
<html lang>タイトルと説明を翻訳し、すべての言語バージョンを hreflang にリンクします。
オプション1: App RouterでNext。jsを国際化する
これは、 公式Next。js国際化ガイド (執筆時点ではバージョン 16。3)。
ステップ1: ルートを言語セグメントの下に配置する
ページとレイアウトを に移動します app/[lang]/。次に、各ページはルートパラメータとしてロケールを受け取ります:
// app/[lang]/page.tsx
export default async function Page({ params }: PageProps<'/[lang]'>) {
const { lang } = await params;
return <h1>{lang}</h1>;
}ルーティングではサブパス(/fr/products) またはドメイン (my-site.fr/products)。サブパスはホストが簡単で、すべての言語を 1 つのドメインに保持します。
ステップ2: proxy。jsで言語を検出してリダイレクトする
Next。js 16では middleware ファイル規約の名前が に変更されました proxy (コードモードがあります: npx @next/codemod@canary middleware-to-proxy .)。プロキシは、URL にすでにロケールがあるかどうかを確認し、ない場合はリダイレクトします
// proxy.js
import { NextResponse } from 'next/server';
const locales = ['en', 'fr', 'de'];
function getLocale(request) {
// Read Accept-Language, e.g. with @formatjs/intl-localematcher and negotiator
return 'en';
}
export function proxy(request) {
const { pathname } = request.nextUrl;
const hasLocale = locales.some((l) => pathname.startsWith(`/${l}/`) || pathname === `/${l}`);
if (hasLocale) return;
request.nextUrl.pathname = `/${getLocale(request)}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}
export const config = {
matcher: ['/((?!_next).*)'],
};自動リダイレクトには注意してください。Google のガイダンス 多言語サイト ユーザーに次の選択を許可することをお勧めします: “ページの他の言語バージョンにハイパーリンクを追加することを検討してください。” URL にロケールがない場合にのみリダイレクトし、訪問者(または Googlebot)が要求したロケールから離れることはなく、常に言語スイッチャーを表示します。
ステップ3: 言語ごとに辞書をロードする
言語ごとに 1 つの JSON ファイルを保持し、サーバーにロードします
// app/[lang]/dictionaries.ts
import 'server-only';
const dictionaries = {
en: () => import('./dictionaries/en.json').then((m) => m.default),
fr: () => import('./dictionaries/fr.json').then((m) => m.default),
};
export type Locale = keyof typeof dictionaries;
export const hasLocale = (l: string): l is Locale => l in dictionaries;
export const getDictionary = async (l: Locale) => dictionaries[l]();// app/[lang]/page.tsx
import { notFound } from 'next/navigation';
import { getDictionary, hasLocale } from './dictionaries';
export default async function Page({ params }: PageProps<'/[lang]'>) {
const { lang } = await params;
if (!hasLocale(lang)) notFound();
const dict = await getDictionary(lang);
return <button>{dict.products.cart}</button>;
}App Router ページはデフォルトで Server Components であるため、辞書はブラウザに出荷されません。ドキュメントにも説明されています next/root-paramsこれにより、任意のサーバーコンポーネントを読み取ることができます lang 小道具を通して渡すことなく。
ステップ4: 各言語をプレレンダリングし、HTMLのlang属性を設定する
// app/[lang]/layout.tsx
export async function generateStaticParams() {
return [{ lang: 'en' }, { lang: 'fr' }, { lang: 'de' }];
}
export default async function RootLayout({ children, params }: LayoutProps<'/[lang]'>) {
return (
<html lang={(await params).lang}>
<body>{children}</body>
</html>
);
}ステップ5: hreflangと正規タグを追加する
Next。js はどのページが互いの翻訳であるかを認識しないため、それを宣言します。と メタデータ API, alternates 標準リンクと hreflang リンクの両方を出力します
// app/[lang]/pricing/page.tsx
export async function generateMetadata({ params }) {
const { lang } = await params;
return {
alternates: {
canonical: `https://example.com/${lang}/pricing`,
languages: {
en: 'https://example.com/en/pricing',
fr: 'https://example.com/fr/pricing',
de: 'https://example.com/de/pricing',
'x-default': 'https://example.com/en/pricing',
},
},
};
}各言語バージョンには、それ自体を含むすべてのバージョンをリストする必要があります。に関する私たちの記事 自己参照hreflangタグ それがなぜ重要なのかを説明します。
重いものを持ち上げる図書館
Next。jsのドキュメントには、ルーティングと翻訳のためのいくつかのライブラリがリストされています next-intl, next-international, next-i18n-router, paraglide-next, lingui そして tolgee。複数形、番号と日付の書式設定、タイプセーフなメッセージ キーが追加されます。小さなサイト以外のものについては、自分で書くのではなく、サイトを選択してください。
オプション1b: ページルーター
プロジェクトがまだ使用している場合 pages/ ディレクトリでは、Next。js にはバージョン 10 以降、i18n ルーティングが組み込まれています。にロケールを追加します next.config.js:
module.exports = {
i18n: {
locales: ['en-US', 'fr', 'de'],
defaultLocale: 'en-US',
},
};これはあなたに与えます /fr/blog そして /de/blog 自動的に設定 <html lang>。によると、 ページ ルーターガイド2つの制限が重要です。hreflangを自分で追加します( next/head)、および “国際化されたルーティングは統合されません output: 'export'”。静的エクスポートには、App Router アプローチまたは別のセットアップが必要です。
コードルートのコスト
コード ルートは、文字列がコンポーネント内に存在する製品 UI にとって正しい選択です。他のものすべてのために高価になります:
- コード外のコンテンツ (ヘッドレス CMS、製品フィード、ユーザー生成コンテンツ)には独自の翻訳パイプラインが必要です。
- 新しい文字列ごとに リリース前にキーとすべての言語での翻訳が必要です。
- 開発者以外の人は翻訳を修正できません 翻訳管理ツールを追加しない限り、プル リクエストはありません。
- 言語が増えるということは、ファイルが増えることを意味します 同期を保つため。
オプション2: コードを変更せずにNext。jsサイトを翻訳する
ConveyThis のような Web サイト翻訳サービスは、Next。js アプリがレンダリングする HTML を翻訳するため、辞書を作成したりルートを変更したりする必要はありません。
ステップ1: アカウントを作成し、ドメインを追加します
ConveyThis アカウントを作成しますドメインを追加し、ソース言語とターゲット言語を選択します。
ステップ2: スクリプトをルートレイアウトに追加する
ConveyThis APIキーを含むスクリプトURLを提供します。App Routerで、1 回追加します app/layout.tsx と next/script:
// app/layout.tsx
import Script from 'next/script';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
<Script
src="https://cdn.conveythis.com/javascript/conveythis.js?api_key=YOUR_API_KEY"
strategy="afterInteractive"
/>
</body>
</html>
);
}ウィジェットはページの変更とクライアント側のナビゲーションを監視するため、最初のロード後に React がレンダリングするコンテンツや、完全なリロードなしで変更されるルートも翻訳されます。また、ページを設定します lang 表示されている言語に帰属します。一般的な手順は私たちと同じです React翻訳ヘルプ記事 そして JavaScript 統合ガイド.
ステップ3: SEOに優しいURL構造を選択する
ブラウザでテキストを交換するスクリプトは訪問者にとって十分ですが、検索エンジンがテキストにインデックスを付けるには言語ごとに個別の URL が必要です。ConveyThis ダッシュボードで、 を選択します サブドメイン (fr.example.com) または サブディレクトリ (example.com/fr/) URL 構造の下。翻訳されたページは、hreflang タグが追加された独自の URL で提供されます。カスタムビルド サイトの場合、通常はサブドメインの方が簡単な選択です。Next。js ホストはメイン ドメインにサービスを提供し続け、言語ごとに 1 つの CNAME レコードを追加します。一方、サブディレクトリはドメイン全体を ConveyThis にルーティングすることを意味します。どちらのオプションも事業計画以上にあります; the サブドメインとサブディレクトリのヘルプ記事 それぞれに必要な DNS レコードについて説明します。ドメインがすでに Cloudflare 上にある場合は、 Cloudflare Workers(O2O)のセットアップ ゾーンを所定の位置に保ちます。
ステップ 4: 翻訳を確認して改良します
機械翻訳により、最初の完全なバージョンが数分で得られます。次に、ビジュアル エディターを使用してコンテキスト内の文言を調整し、用語集にブランド用語を追加し、翻訳者またはチームの役割を持つ同僚を招待します。の完全なリストを参照してください 機能ページ.
コードルートかノーコードルートか?
| アプリルーター i18n(コード) | ConveyThis(コードなし) | |
|---|---|---|
| セットアップ | ルートの再構築、プロキシ、辞書の追加、メタデータ | SEO URL 用の 1 つのスクリプト タグと DNS |
| テキストの由来 | あなたの辞書 | CMS コンテンツを含め、ページがレンダリングするものは何でも |
| 翻訳を編集する人 | 開発者(または TMS) | ダッシュボードにアクセスできる人 |
| フレフラン | で追加します alternates | サブディレクトリまたはサブドメイン URL で追加されます |
| に 最適 | アプリのUI文字列、フルコントロール | マーケティング サイト、CMS コンテンツ、多くの言語 |
| 費用 | 開発者 時間 | 言葉と言語に基づいた計画(価格設定) |
ログイン アプリ用のコードベースの i18n、マーケティング サイトおよびヘルプ センター用の翻訳サービスなど、多くのチームがこれらを組み合わせています。
Next。js の多言語 SEO チェックリスト
- 言語ごとに1つのURL(
/fr/…またはfr.example.com)、すべての言語で同じ URL が使用されることはありません。 <html lang>ページの言語と一致します。- タイトルとメタ説明は言語ごとに翻訳されています。
- 翻訳された各ページの正典は、英語のページではなく、それ自体を指します。
- Hreflang には、ページ自体を含むすべての言語バージョンと、
x-default. - サイトマップにはすべての言語 URL が含まれています。
- 状態を変更するドロップダウンだけでなく、実際のリンクを備えた表示可能な言語スイッチャー。
- 訪問者が要求した言語から強制的にリダイレクトされることはありません。
より大きな全体像については、こちらをご覧ください 多言語SEOの概要.
よくある質問
Next。js には翻訳が組み込まれていますか? 国際化が組み込まれています ルーティング Pages Router にあり、App Router の i18n パターンが文書化されています。翻訳されたテキスト自体は、辞書、図書館、または翻訳サービスから取得されます。
Middleware。js に何が起こったのでしょうか? Next。js 16では、 middleware ファイル規約は非推奨となり、 に名前が変更されました proxy。ロケール検出のロジックは同じです。
Next。js は hreflang タグを自動的に追加しますか? いいえ。使用 alternates.languages App Router メタデータ内、または next/head ページルーターで。
静的にエクスポートされた Next。js サイトを翻訳できますか? ページルーターi18nルーティングは動作しません output: 'export'、 静的エクスポートではプロキシはサポートされていません。事前に生成されたものを使用します [lang] ルート、または独自のサブディレクトリまたはサブドメインから翻訳されたページを提供する翻訳サービス。
次の四半期ではなく、今週中に Next。js サイトを複数の言語で公開したいですか? ConveyThis アカウントを作成します、 スクリプトをルートレイアウトに追加し、SEOプランに合ったURL構造を選択します。