技術

Next.jsで実現する多言語対応サイトの構築:グローバルなリーチを10倍に拡大するガイド

App Routerを活用した多言語実装の設計の思想と技術的な決断の全貌

2025-04-03
23分
Next.js
App Router
多言語対応
国際化対応
Web開発
AI協働開発
コンテンツ戦略
吉崎 亮介

吉崎 亮介

株式会社和談 代表取締役社長 / 株式会社キカガク創業者

Next.jsで実現する多言語対応サイトの構築:グローバルなリーチを10倍に拡大するガイド

世界に届ける声 ― 多言語化の可能性と価値

「自分の考えを世界中の人に届けたい」

長くこの思いを抱き続けてきた。しかし正直なところ、個人ブログの多言語対応などリソース的に夢のまた夢だと思っていた。何しろ全ページの英語化、UI 要素の翻訳、URL の再設計といった作業があり、一人でやるにはあまりにも膨大な量だからだ。

ところが、AI の進化が自分の状況を大きく変えた。もしかしたら本当に実現できるかもしれないと胸が高鳴り、ダメ元で挑戦してみることにした。

今回は、自分自身が経験した試行錯誤の裏側、失敗と成功、そして Next.js の App Router を使った多言語対応の実践から得た知見を共有する。技術的な解説にとどまらず、実際に自分が感じた驚きや発見を伝えたい。

ウェブの言語分布と多言語化の威力

多言語対応の重要性を考えるきっかけになったのは、ウェブの言語分布に関するデータを見たことだった。様々な調査結果を参照して、私は英語対応すべきだと確信した。

グラフを読み込み中...

W3Techs の調査1によると、トップサイトのおよそ半数(49.1%)が英語であり、日本語はわずか 5.1%にすぎない。他の調査でも英語の優位性は明らかだった23

この数字を見たとき、自分の中でハッとするものがあった。つまり、日本語だけで発信していると、潜在的な読者のおよそ 10 分の 1 にしかリーチできていないことになる。英語に対応するだけで、理論上は読者数が 10 倍になる可能性があるわけだ。個人ブロガーとしては見逃せない事実だと思った。

AI 翻訳の品質向上がもたらした転機

多言語化の最大の壁は常に翻訳コストだった。記事を英語に翻訳するだけで何時間もかけて苦労していたし、機械翻訳は不自然で、プロの翻訳者に依頼するには予算が厳しかった。

ところが最近、Claude Sonnet 3.7 のような AI の翻訳能力が驚くほど高くなっていると感じている。試しに自分の記事を翻訳させてみたところ、自分で訳すよりよほど自然な英語に仕上がっていた。これは本当に驚きだった。

とはいえ単なる翻訳だけでは足りないことにも気づいた。言語が違えば文化も違い、暗黙の了解が通じない場合がある。たとえば「猫の手も借りたい」という日本語表現は、そのまま英語にしても意味が伝わらない。

そこで自分は、AI に「言語だけでなく文化的背景も考慮して翻訳・加筆してほしい」と具体的に指示を与えるようにした。これが大きな違いを生み出した。

たとえば、この点に配慮して翻訳時に加筆修正してもらった点の例は以下の通りである。

  • 金額表現の調整
    「数十万円」という表現は英語では「several thousand dollars」として、具体的なドル換算は避けつつ規模感が伝わるようにした。

  • 文化的背景の補足
    日本の新卒一括採用や企業内教育などは、前提知識がなくても理解できるようにコンテキストの補足を追加した。

  • キカガクの説明追加
    「キカガク」について「Kikagaku, the company I founded」という補足をつけて、著者との関係性が分かるようにした。

  • 慣用表現の置き換え
    「付け焼き刃」「猫の手も借りたい」といった日本語表現を文脈に合わせて意訳し、英語表現で近いものに変えた。

  • 教育システムの説明
    京都大学や大学院などの話も、国際的な読者に理解してもらえるように文脈を補足しつつ翻訳した。

  • 文体の保持
    「である調」の断定的な表現や、著者の内省的な語りの特徴が英語でもなるべく伝わるように気をつけた。特に“I believe”のような表現や、断定的な文末を使うことで著者の思考プロセスが残るようにした。

  • 専門用語の正確性
    「Vibe Coding」などの専門用語はそのまま残しつつ、簡単な説明を加えて分かりやすくした。

このように、単なる言語変換だけではなく、文化的文脈も含めて翻訳する重要性を改めて実感した。多言語化を検討しているなら、この点にこそ注目してほしいと思う。

わずか 6 時間で実現した多言語対応の衝撃

正直に言うと、最初は「週末をつぶしてどうにか形にできれば上出来だろう」と思っていた。多言語サイトの構築は通常、数週間かかる大仕事だからだ。

しかし結果的には、わずか 6 時間で全ページの英語化対応と確認・修正を完了できた。自分でも信じられないほど早く済んだ。

夕方に作業を始め、ディレクトリ構造の計画から URL スキームの設計、言語切替機能の実装まで、AI とのペアプログラミングのように進めていったら想像以上にスムーズに進行した。

コストの面でも驚きだった。Claude Sonnet 3.7 の利用料は約 60 ドル(1 万円以下)にしかならなかった。システム開発会社に依頼すれば数百万円かかる規模の作業を一人でやったことになるので、コストパフォーマンスはかなり高い。自分の労力というコストは別だとしても、これほどの省力化は想定外だった。

夜中に動作確認をしながら「本当に動くのだろうか」と半信半疑だったが、テスト結果を見て確信に変わった。この体験は AI との協働開発の可能性を強く感じさせるものだった。

Next.js App Router による多言語実装の戦略的決断

多言語サイトを作ろうと決めたとき、最初の難題はURL 構造の設計だった。これは SEO、ユーザー体験、将来の拡張性に大きく関わる重要な決定要素だ。

URL 構造の選択肢と意思決定プロセス

どのアプローチを取るべきか迷ったので、主な選択肢を整理してみた。

図表を生成中...

3 つの選択肢の中でサブパス方式に決めた理由は以下の通りだ。

  1. SEO が明確になる
    各言語版がユニークな URL を持つため、検索エンジンが判別しやすい
  2. Next.js App Router との相性が良い
    ファイルベースルーティングと自然に統合できる
  3. 実装がシンプル
    動的ルートやミドルウェアを使えばスムーズに実装可能
  4. 拡張が容易
    将来的に新しい言語を増やすのも簡単

この選択が後々の実装を楽にしてくれた。多言語サイトを作る際は、最初の URL 構造を入念に検討することを強く勧める。

ディレクトリ構造の変革――従来版から新版へ

URL 構造を決めた後は、ディレクトリ構造の再設計が課題になった。Next.js の App Router はファイルシステムベースでルーティングを行うので、ディレクトリ構造がそのまま URL に影響する。

変更前と変更後を図にして比べてみた。

Before

図表を生成中...

After

図表を生成中...

これでURL の最初のセグメントが言語コード(/ja/、/en/など)になった。
たとえば、日本語版の技術記事は/ja/tech/article-slug、英語版なら/en/tech/article-slugとなる。

ここで最大の問題は既存コンポーネントとページをどのように移行するかだった。具体的には下記のような点だ。

  1. ページコンポーネントを移行
    既存ページをすべて新構造に合わせて移動する必要があった
  2. 参照パスの更新
    インポートパスを修正しなくてはならなかった
  3. 言語パラメータの伝播
    すべてのページで言語情報を扱う必要があった

特に、リンク生成やデータ取得の部分で言語パラメータを考慮する必要があり、想像以上に手間がかかった。

あるページでは次のようなエラーが出たことがあった。

Error: Page "/[lang]/tech/page" is missing exported function "generateMetadata".

言語パラメータを含む新ルート構造でメタデータ生成の関数が合わなくなっていたのだ。AI と協力しながら、各ページのメタデータ生成を修正した。

// Before
export async function generateMetadata(): Promise<Metadata> {
  return {
    title: "技術記事 | Wadan Blog",
    // ...
  };
}
 
// After
export async function generateMetadata({
  params,
}: {
  params: { lang: string };
}): Promise<Metadata> {
  const title = params.lang === "en" ? "Tech Articles" : "技術記事";
  return {
    title: `${title} | Wadan Blog`,
    // ...
  };
}

こういった調整を何十ファイルにも行う必要はあったが、AI のおかげで予想より早く片付いた。まずは 1 ページで完全に動くように直し、そのパターンを横展開する方法が効率的だった。

URL 変換を担うミドルウェアの実装

多言語サイトの中核になったのは、Next.js のミドルウェア機能だ。これは各リクエストを処理する前に実行される特別な関数で、URL の変換や言語検出に使える。

自分が書いたミドルウェアで重要だったのは、主に以下の 3 つの機能だ。

  1. 言語検出と自動リダイレクト
    ルート URL アクセス時に適切な言語版へ飛ばす
  2. 既存 URL から新 URL への変換
    古い形式の URL を新形式にリダイレクト
  3. 言語パラメータの検証と正規化
    無効な言語コードを処理する
// middleware.ts(核心部分のみ抜粋)
export function middleware(request: NextRequest) {
  const pathname = request.nextUrl.pathname;
 
  // ルートパス(/)へのアクセスを適切な言語版にリダイレクト
  if (pathname === "/") {
    const preferredLocale = getPreferredLocale(request);
    return NextResponse.redirect(new URL(`/${preferredLocale}`, request.url));
  }
 
  // 既存URL(/tech/article)を新形式(/ja/tech/article)に変換
  if (isLegacyUrlPattern(pathname)) {
    const segments = pathname.split("/").filter(Boolean);
    const category = segments[0];
    const slug = segments[1];
    const preferredLocale = getPreferredLocale(request);
 
    // 301(永続リダイレクト)でSEO効果を維持
    return NextResponse.redirect(
      new URL(`/${preferredLocale}/${category}/${slug}`, request.url),
      { status: 301 }
    );
  }
 
  // 言語コードのチェックと追加
  // ...
}

大変だったのは、リダイレクトループを防ぐことだった。最初に書いたときは特定条件で無限リダイレクトが起こり、ブラウザが「Too many redirects」というエラーを返した。

原因はミドルウェアの条件分岐が甘かったせいで、リダイレクト後の URL でも同じ処理が走ってしまうことにあった。厳密なチェックと、すでにリダイレクトした URL を識別する仕組みが必要だった。

また、ブラウザの言語設定から適切な言語を検出するのに@formatjs/intl-localematchernegotiatorを使った。これでユーザーのブラウザ言語に合わせたリダイレクトが可能になった。

import { match } from "@formatjs/intl-localematcher";
import Negotiator from "negotiator";
 
function getPreferredLocale(request: NextRequest): string {
  const defaultLocale = "en";
  const locales = ["en", "ja"];
 
  const headers = {
    "accept-language": request.headers.get("accept-language") || "",
  };
  const negotiator = new Negotiator({ headers });
 
  let languages = negotiator.languages();
  if (!languages || languages.length === 0) {
    return defaultLocale;
  }
 
  const locale = match(languages, locales, defaultLocale);
  return locale;
}

テストを繰り返し、ブラウザ言語設定がない場合やサポート外言語の場合など様々なケースに対応させる必要があった。結果的に、このミドルウェアが多言語サイトの心臓部として機能し、ユーザー体験と SEO の両面を支えることになった。

Playwright MCP による革新的テスト手法

多言語サイトを実装した後の課題は、すべてのページが正しく言語切り替えできているか検証することだった。ページ数が多いほど手動チェックは辛く、見落としも起きやすい。

そこで Twitter で見かけたMicrosoft Playwright Multiple Client Protocol (MCP)という新ツールを試してみたところ、これが非常に革新的だった。

驚くほど簡単な設定

最初は「何やら面倒そうだ」と思ったが、Playwright MCP の設定は驚くほど簡単だった。Claude(Roo Code)の設定に以下を加えるだけだった。

{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}

これで AI がブラウザを操作し、Web サイトをテストできるようになるというのだから信じがたいほどシンプルだった。

テキストログベースのテストと AI 連携の威力

Playwright MCP の最大の特徴は、テキストログベースで結果を確認できることだ。多くのツールはスクリーンショットしか撮らないが、これはページ内容をテキストとして認識して問題を指摘してくれる。

実際のログ例を見てほしい。

[Playwright] Navigating to http://localhost:3000/en/tech/nextjs-app-router-basics
[Playwright] Current URL: http://localhost:3000/en/tech/nextjs-app-router-basics
[Playwright] Page title: "Next.js App Router Basics | Wadan Blog"
[Playwright] Checking links on page...
[Playwright] Found link with text: "Read more" [OK]
[Playwright] Found link with text: "続きを読む" [ERROR - Japanese text on English page]
[Playwright] Link href="/tags/Next.js" [ERROR - Missing language prefix]
[Playwright] Link href="/en/tags/App-Router" [OK]

「続きを読む」ボタンが英語ページに残っているエラーや、タグリンク(/tags/Next.js)に言語プレフィックスがないなど、見逃しがちな問題を一目で洗い出してくれる。

さらに、このテキストログはそのまま AI に共有できるので、問題分析と修正提案を一気に進められる。実際、AI にログを渡したところ、すぐに以下のような具体的修正案が出てきた。

// 日本語テキスト問題の修正例
const readMoreText = lang === 'en' ? 'Read more' : '続きを読む';
// ...
<Link ...>{readMoreText}</Link>
 
// 言語プレフィックス欠如問題の修正例
<Link href={`/${lang}/tags/${tag}`}>{tag}</Link>

これは従来のテスト手法では想像できない効率の良さだった。AI との連携によって、テスト結果 → 問題分析 → 修正がシームレスに進むのだ。

モンキーテストで発見した典型的な問題

Playwright MCP を用いたテストで見つかった主な問題は以下の 2 つだった。

  1. 翻訳漏れの UI 要素
    「続きを読む」「共有する」といったボタンやラベルの日本語表記が英語ページに残るなど、単純な見落としが多かった。

  2. URL 生成ミス
    言語プレフィックスの無いリンクや、別言語へのリンクが混在するなど、URL 生成ロジックのミスが目立った。

これらはいずれも見た目には影響が薄いので、手動確認だけでは発見が遅れがちなものだった。こうした問題を事前に洗い出して修正できたのは、Playwright MCP の功績が大きいと思う。

AI との協働による劇的な効率化の内幕

多言語サイト構築を進める過程で、AI との協働によって生産性が劇的に上がる体験をした。具体的にどう有効だったのか、実例とともに共有する。

効果的な AI 協働の具体的アプローチ

AI をうまく使うポイントは、具体的で的確な情報を与えることに尽きる。以下の 3 つのアプローチが特に役立った。

  1. 具体的なエラーメッセージの共有

多言語対応の初期段階で以下のようなエラーに遭遇した。

Error: ./lib/i18n/utils.ts:10:1 Module not found: Cannot resolve 'fs/promises'

これはクライアントコンポーネントからサーバー側のファイルシステム操作を呼び出していたのが原因だった。AI に状況を細かく伝えると、すぐに「クライアント/サーバーコードの分離」を提案してくれた。

// lib/i18n/client.ts - クライアント側で安全に使える関数
export function getLocaleFromPathClient(path: string): string {
  const segments = path.split("/").filter(Boolean);
  return segments[0] || "ja";
}
 
// lib/i18n/server.ts - サーバー側のみで使う関数(fs/promises を使用)
import { readFile } from "fs/promises";
export async function getTranslationsFromFile(locale: string) {
  // ファイル操作を含むコード
}

抽象的に「i18n でエラーが出たのだがどう対処すればいい?」と聞くよりも、具体的なエラー内容と状況を伝えるほうがはるかに効果的だった。

  1. Playwright MCP のテスト結果フィードバック

先述のとおり、テストツールからの指摘を具体的に AI に渡すと、すぐに修正案が返ってくる。たとえば英語ページ(/en/*)に日本語 UI が残っているという報告をまとめて伝えた。

1. 「続きを読む」ボタン - ArticleCard.tsxの17行目
2. 「記事」というラベル - CategorySection.tsxの34行目
3. 「共有する」というボタン - ShareButtons.tsxの12行目

これらを条件分岐で一括管理するにはどうすればいいかと尋ねると、以下のように i18n の共通関数を使った包括的な手法を提案してくれた。

// lib/i18n/translations.ts
export const translations = {
  ja: {
    readMore: "続きを読む",
    articles: "記事",
    share: "共有する",
    // 他の翻訳
  },
  en: {
    readMore: "Read more",
    articles: "Articles",
    share: "Share",
    // 他の翻訳
  },
};
 
// 使用例
import { translations } from "@/lib/i18n/translations";
 
function ArticleCard({ lang, ...props }) {
  const t = translations[lang];
  return (
    // ...
    <Link>{t.readMore}</Link>
  );
}

ハードコーディングされた日本語テキストを個々に修正するより、共通化されているほうがはるかにミスが少なく、管理しやすい。

  1. 実装計画の段階的レビュー

大きな実装に取りかかる前に、AI に計画をレビューさせるのも効果的だった。
たとえば、ディレクトリ構造を以下のように変更する予定だと伝えて注意点を聞いた。

変更前: app/tech/[slug]/page.tsx
変更後: app/[lang]/tech/[slug]/page.tsx

すると、下記のような重要なポイントを指摘してくれた。

  • Next.js 15 での非同期パラメータ処理の注意
  • メタデータ生成関数の引数パターン変更の必要
  • ページ間リンク生成時に lang パラメータを考慮する必要
  • 静的/動的レンダリング戦略の再考

特に generateStaticParams の更新など、言語パラメータを追加すると SSG の仕組みが変わるという点は盲点だった。こうした事前レビューで大きなトラブルを回避できた。

多言語化プロジェクトでの AI 活用の教訓

今回のプロジェクトを通じて得られた AI 活用に関する教訓は以下の 3 つにまとめられる。

  1. 具体的なコンテキストの提供が鍵

抽象的な質問よりも、エラーログやコード断片、テスト結果といった具体的情報を提供するほうが、はるかに的確な回答を得られる。

  1. 段階的に問題を分解する

「多言語対応の実装」という大きな課題を、

  • URL スキームの決定
  • ディレクトリ構造の設計
  • ミドルウェアの実装
  • 言語切替 UI の実装
  • 各コンポーネントの国際化
  • テストと検証

といったステップに分解し、段階ごとに AI にフィードバックをもらうことでスムーズに進められる。

  1. AI の得意・不得意を理解する

AI はパターン適用やエラー解析、具体的なコード例を提案するのが得意だが、アーキテクチャ全体の最終決定やデザイン上の美しさなどは人間が判断したほうがいい。自分は戦略と優先順位を決め、繰り返し作業や細かい実装は AI に任せる形が最も効率的だった。

結論 ― 多言語化がもたらす可能性と今後の展望

ここまでの道のりを振り返ると、Next.js の App Router を使った多言語サイト構築と、AI との協働開発という 2 つの実験によって、開発アプローチが大きく変わったと感じている。

得られた最大の学び

  1. URL 設計とディレクトリ構造の重要性

多言語対応で最初に学んだのは、基礎設計を甘く見てはいけないということだ。URL 構造とディレクトリ構造は実装全体を左右する基盤であり、SEO やユーザー体験にも直結する。最初に時間をかけて検討したおかげで、後の作業がずいぶん楽になった。

  1. Playwright MCP の革新性

テキストログによるテスト結果を AI にフィードバックするという発想が革新的だった。モンキーテストでも細かい問題を確実に見つけられ、しかも修正がスピーディに行える。数日かかっていた検証が数時間で終わるというのは、生産性の大きな飛躍だ。

  1. AI との効果的な協働スタイル

抽象的な指示ではなく、具体的なログやエラーメッセージ、コードを提示して段階的に問題を解くことで、爆発的に効率が上がることを実感した。戦略的判断は人間が行い、繰り返し作業や詳細実装は AI に任せるという役割分担がうまく機能した。

これからの多言語コンテンツ戦略

今回の経験を通じて、多言語対応が単なる「付加機能」ではなく、グローバルに読者へ届くための必須戦略だと強く認識した。AI との協働によって、多言語化のハードルは確実に下がっている。かつては翻訳者や大規模チームが必要だった作業も、今では個人開発者でも実現可能だ。

自分のコンテンツを世界に届ける挑戦を、ぜひ多くの人にやってみてほしい。技術的な壁は確かにあるが、適切なツールと戦略を使えば、想像以上にスムーズに進むはずだ。

強調しておきたいのは、多言語化は単なる技術課題ではなく、世界の読者とつながるための手段だという点だ。技術的な実装の裏にある、グローバルなコミュニケーションと価値の共有こそが本来の目的だと思っている。

自分のブログを多言語化したことで、日本国内だけでなく海外の読者ともつながれる可能性を感じている。まだ始まったばかりだが、これからがとても楽しみだ。読者のみなにも、自分の言葉を世界に届ける旅をぜひ始めてみてほしい。

出典

Footnotes

  1. W3Techs「Usage statistics of content languages for websites」(2025 年)トップ 1,000 万サイトの言語使用状況調査

  2. DataProvider「Language distribution across 136M websites」(2023 年)世界 1.36 億サイトの言語分析

  3. Observatory of Linguistic and Cultural Diversity on Internet (OBDILCI)「Web language distribution」(2024 年)全ウェブを対象とした言語分布推計

吉崎 亮介

吉崎 亮介

株式会社和談 代表取締役社長 / 株式会社キカガク創業者

「知の循環を拓き、自律的な価値創造を駆動する」をミッションに、組織コミュニケーションの構造的変革に取り組んでいます。AI技術と社会ネットワーク分析を活用し、組織内の暗黙知を解放して深い対話を生み出すことで、創造的価値が持続的に生まれる組織の実現を目指しています。

最新のインサイトを受け取る

定期的なニュースレターで、技術とビジネスの境界領域に関する最新の記事や独自のインサイトをお届けします。