Next.js国際化入門 - 多言語対応サイトを作る

中級 | 45分 で読める | 2025.12.12

公式ドキュメント

今回やること

Next.jsで多言語対応を行う時は、翻訳ファイルだけでなくURL設計、言語切替、SEOも一緒に考える必要があります。

国際化は後から足すほど影響範囲が広がります。最初にロケールの持ち方とURL方針を決めることが重要です。

この記事では次を学びます。

  • i18nルーティング
  • 翻訳ファイル管理
  • next-intl設定
  • 動的ロケール切替
  • SEO対応

Step 1: セットアップ

実践メモ: next-intlはApp Router対応の国際化ライブラリです。Server ComponentsとClient Componentsの両方で翻訳関数が使えます。

npm install next-intl

Step 2: 翻訳ファイル

// messages/ja.json
{
 "home": {
 "title": "ホームページ",
 "welcome": "ようこそ、{name}さん"
 },
 "nav": {
 "home": "ホーム",
 "about": "会社概要",
 "contact": "お問い合わせ"
 }
}

// messages/en.json
{
 "home": {
 "title": "Home Page",
 "welcome": "Welcome, {name}"
 },
 "nav": {
 "home": "Home",
 "about": "About",
 "contact": "Contact"
 }
}

Step 3: next.config.js

const withNextIntl = require('next-intl/plugin')();

module.exports = withNextIntl({
 // 他の設定
});

Step 4: i18n設定

// i18n.ts
import { getRequestConfig } from 'next-intl/server';

export default getRequestConfig(async ({ locale }) => ({
 messages: (await import(`./messages/${locale}.json`)).default
}));

注意: ミドルウェアのmatcher設定で静的ファイルパスを除外しないと、画像やCSSにもリダイレクトが適用されてしまいます

Step 5: ミドルウェア

// middleware.ts
import createMiddleware from 'next-intl/middleware';

export default createMiddleware({
 locales: ['ja', 'en'],
 defaultLocale: 'ja'
});

export const config = {
 matcher: ['/((?!api|_next|.*\\..*).*)']
};

Step 6: レイアウト

// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';

export default async function LocaleLayout({
 children,
 params: { locale }
}: {
 children: React.ReactNode;
 params: { locale: string };
}) {
 const messages = await getMessages();

 return (
 <html lang={locale}>
 <body>
 <NextIntlClientProvider messages={messages}>
 {children}
 </NextIntlClientProvider>
 </body>
 </html>
 );
}

Step 7: 翻訳の使用

// app/[locale]/page.tsx
import { useTranslations } from 'next-intl';

export default function HomePage() {
 const t = useTranslations('home');

 return (
 <div>
 <h1>{t('title')}</h1>
 <p>{t('welcome', { name: 'Alice' })}</p>
 </div>
 );
}

Step 8: ロケール切替

'use client';
import { useLocale } from 'next-intl';
import { useRouter, usePathname } from 'next/navigation';

export function LocaleSwitcher() {
 const locale = useLocale();
 const router = useRouter();
 const pathname = usePathname();

 const switchLocale = (newLocale: string) => {
 const newPath = pathname.replace(`/${locale}`, `/${newLocale}`);
 router.push(newPath);
 };

 return (
 <select value={locale} onChange={(e) => switchLocale(e.target.value)}>
 <option value="ja">日本語</option>
 <option value="en">English</option>
 </select>
 );
}

SEO対応

// app/[locale]/page.tsx
export async function generateMetadata({ params: { locale } }) {
 const t = await getTranslations({ locale, namespace: 'home' });

 return {
 title: t('title'),
 alternates: {
 languages: {
 ja: '/ja',
 en: '/en',
 },
 },
 };
}

多言語対応で最初に決めること

国際化は、翻訳ファイルを用意するだけでは終わりません。URLにロケールを含めるか、デフォルト言語をどう扱うか、SEOのalternate設定をどう出すかを先に決める必要があります。後からURL設計を変えると、リンクや検索評価への影響が大きくなります。

翻訳キーは画面ごとに整理すると運用しやすくなります。日本語の文章そのものをキーにすると、文言変更のたびにキーも変わりやすいため、home.titleやnav.contactのように役割で命名するほうが保守しやすくなります。

運用でつまずきやすい点

  • 翻訳漏れがある画面だけ英語やキー名のまま表示される
  • 日付、通貨、数値の表示形式が言語ごとに合っていない
  • 画像内テキストが翻訳対象から漏れる
  • canonicalとalternateの指定が矛盾する

動作確認

多言語対応を入れたら、次を確認します。

確認項目見る場所OKの状態
URL/ja/en各言語ページが表示される
翻訳画面文言キー名がそのまま表示されない
言語切替切替UI同じページの別言語へ移動する
SEOHTML headalternates.languages が出る
404存在しないlocale想定通りに扱える

翻訳漏れは見た目だけでは気づきにくいため、主要画面を言語ごとに確認します。

練習

次の小さな多言語ページを作ってください。

  1. jaen の翻訳JSONを作る
  2. トップページのタイトルと説明文を翻訳する
  3. /ja/about/en/about を表示する
  4. 言語切替コンポーネントを作る
  5. generateMetadata で言語ごとのtitleを出す

次のステップ

Next.jsのルーティング自体が不安な場合は Next.js App Router実践ガイド を先に確認してください。SEO観点は 静的サイト・動的サイトの違いリダイレクトとcanonical も関連します。

まとめ

next-intlでNext.jsアプリを簡単に多言語対応できます。ルーティングとSEOも適切に設定しましょう。

参考リソース

← 一覧に戻る
PR
PR
PR
PR