|
ドキュメント
デモを予約プラットフォーム
プラットフォームMCPCLIAPIワークフロー
ガイド
変更履歴

ローカライゼーション

  • 概要
  • 翻訳API
  • Webアプリのローカライゼーション
  • モバイルアプリのローカライズ
  • Android with strings.xml
  • メールのローカライズ
  • 静的コンテンツ(例: .md、.json)
  • Next.js with Markdoc
  • Rails with i18n

ローカライズ

  • String Catalogを使ったiOS

ワークフロー

  • MCP でエンジンを設定
  • Jiraトリアージ
  • CI/CD

Markdoc を使った Next.js App Router のローカライゼーション

Lingo.dev CLI は、設定した ローカライゼーションエンジン を通して Markdoc ファイルと JSON の UI 文字列カタログを翻訳します。Markdoc は Markdown ベースのオーサリング形式で、型付きの React ベースカスタムタグに対応しており、長文コンテンツとインタラクティブなコンポーネントを組み合わせる Next.js App Router サイトに適しています。

このガイドでは、Next.js App Router サイトをエンドツーエンドでローカライズする手順を解説します。CLI の設定、ロケール別コンテンツの整理、動的ルートでの Markdoc のレンダリング、そして GitHub Actions を使った翻訳の自動化までをカバーします。

デモリポジトリ

一緒に進めるには、lingodotdev/markdoc-nextjs-localization-example を clone または fork してください。このリポジトリには、Markdoc コンテンツを含む動作する Next.js App Router アプリ、Lingo.dev CLI の設定、GitHub Actions のワークフローが含まれています。

Next.js + Markdoc のローカライゼーションの仕組み#

多くの Next.js App Router サイトでは、ローカライズ対象のコンテンツを 2 つのレイヤーに分けています。

レイヤー内容ファイル例
長文コンテンツマーケティングページ、ドキュメント、ブログ記事src/content/[locale]/pages/home.md
UI 文字列ナビゲーションバーのラベル、CTA、ボタンの状態src/content/[locale]/ui.json

ルートは src/app/[lang]/ 配下に置かれ、リクエスト時に対応するロケールのファイルを読み込みます。middleware はブラウザーの Accept-Language ヘッダーからデフォルトのロケールを判定し、/ のようなプレフィックスなしのパスを /en(または最適な一致先)へリダイレクトします。

CLI の markdoc バケットは、frontmatter とカスタムタグを保ったまま Markdoc ファイルを解析し、json バケットは UI 文字列カタログを処理します。どちらも差分のみをローカライゼーションエンジン経由で翻訳し、ソースと並ぶ形でロケール別ファイルを書き出します。

前提条件#

1

ローカライゼーションエンジンを作成する

CLI を実行するたびに、コンテンツは ローカライゼーションエンジン を通過します。これは、適用する LLM モデル、glossary、ブランドボイス、instructions を決める設定です。Lingo.dev dashboard で作成し、API key を生成してください。

2

Node.js を確認する

CLI の利用には Node.js 18 以上が必要です。

bash
node -v
3

Next.js プロジェクトをセットアップする

プロジェクトには App Router(src/app/)と、ロケールごとのコンテンツディレクトリが必要です。デモリポジトリでは src/content/[locale]/ を使い、2 つのサブフォルダー(pages/ と blog/)に加えて ui.json ファイルを配置しています。ルーティングの基本は Next.js internationalization を参照してください。

コンテンツを整理する#

役割ごとにコンテンツを分けましょう。長文ページや記事は Markdoc で管理し、短い UI 文字列は JSON に置くことで、コンポーネントから直接読み込めます。

text
src/content/
  en/                  # Source locale
    pages/home.md      # Long-form Markdoc
    blog/hello.md
    ui.json            # UI strings (navbar, CTAs, button states)
  es/                  # Target locales – generated by Lingo.dev
  fr/
  de/

Markdoc ファイルは、ページごとのメタデータ(title、description、date、author)を記述する frontmatter と、React コンポーネントとしてレンダリングされるカスタムタグをサポートしています。最小構成のページは次のようになります。

markdown
---
title: Author once in Markdoc, ship in every language.
description: An example Next.js App Router app that localizes Markdoc with Lingo.
---

{% inline-callout type="info" %}
This page is authored in Markdoc and translated by Lingo.dev.
{% /inline-callout %}

## Built from three pieces

Markdoc custom tags render as React components – even interactive ones.

CLI を設定する#

プロジェクトルートに i18n.json ファイルを作成します。Markdoc コンテンツ用と UI 文字列カタログ用の 2 つのバケットを定義します。

json
{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.15",
  "locale": {
    "source": "en",
    "targets": ["es", "fr", "de"]
  },
  "buckets": {
    "markdoc": {
      "include": [
        "src/content/[locale]/pages/*.md",
        "src/content/[locale]/blog/*.md"
      ]
    },
    "json": {
      "include": ["src/content/[locale]/ui.json"]
    }
  }
}

[locale] プレースホルダーは、設定した各ロケールコードに展開されます。source: "en" を使うと、CLI は src/content/en/ を読み込み、翻訳済みファイルを src/content/es/、src/content/fr/、src/content/de/ に書き出します。

単一ファイルのカタログ

UI 文字列がロケールごとの 1 ファイルではなく、単一の多ロケール JSON ファイルにまとまっている場合は、json-per-locale バケットタイプを使ってください。バケットタイプの一覧は Static Content Localization を参照してください。

App Router で Markdoc をレンダリングする#

一般的な動的ルートでは、ドキュメントを読み込んで、変換済みのツリーをレンダリングします。デモリポジトリでは、小さなヘルパーを用意しています。

ts
// src/lib/markdoc.ts
export async function loadDoc(
  locale: Locale,
  collection: "pages" | "blog",
  slug: string,
) {
  const raw = await fs.readFile(
    path.join(process.cwd(), "src/content", locale, collection, `${slug}.md`),
    "utf8",
  );
  const ast = Markdoc.parse(raw);
  const frontmatter = ast.attributes.frontmatter
    ? parseFrontmatter(ast.attributes.frontmatter)
    : {};
  const content = Markdoc.transform(ast, { ...schema, variables: { frontmatter } });
  return { frontmatter, content };
}

App Router のページは、ドキュメントとロケール別の UI 文字列を組み合わせる薄いラッパーです。

tsx
// src/app/[lang]/page.tsx
export default async function Home({ params }: PageProps<"/[lang]">) {
  const { lang } = await params;
  const doc = await loadDoc(lang, "pages", "home");
  const { home } = await getMessages(lang);

  return (
    <main>
      <h1>{doc.frontmatter.title}</h1>
      {renderMarkdoc(doc.content)}
    </main>
  );
}

カスタム Markdoc タグ(callout、bento、blog-hero など)は markdoc.schema.ts で宣言し、src/components/markdoc/ 配下の React コンポーネントに接続します。完全な API については Markdoc schema docs を参照してください。

Middleware でロケールを判定する#

Next.js の middleware は、ルートがレンダリングされる前にリクエストを検査します。これを使えば、Accept-Language ヘッダーに基づいて、プレフィックスなしのパスを最も適したロケールへリダイレクトできます。

ts
// src/middleware.ts
export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;
  const hasLocale = locales.some(
    (locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`),
  );
  if (hasLocale) return;

  const locale = pickLocale(request); // parses Accept-Language
  const url = request.nextUrl.clone();
  url.pathname = `/${locale}${pathname === "/" ? "" : pathname}`;
  return NextResponse.redirect(url);
}

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

訪問者はプレフィックスを入力しなくても、/en、/es、/fr、または /de にアクセスできます。

ローカルで翻訳する#

API key を設定して CLI を実行します。

bash
export LINGO_API_KEY="your-api-key"
npx lingo.dev@latest run

CLI はバケットパターンに一致するすべてのファイルを読み込み、lockfile を使って未翻訳のエントリを特定し、差分のみをローカライゼーションエンジン経由で翻訳して、各対象ロケールのディレクトリに結果を書き出します。frontmatter のキー、Markdoc のカスタムタグ、JSON の構造は保持され、変わるのは翻訳対象のテキストだけです。

開発中に特定のロケールだけを対象にするには:

bash
npx lingo.dev@latest run --target-locale es

GitHub Actions で自動化する#

プッシュのたびに翻訳を実行するには、.github/workflows/translate.yml にワークフローファイルを追加します。

翻訳は main に直接コミットされます。手間が少なく、小規模チームに最適です。

yaml
name: Translate
on:
  push:
    branches: [main]
permissions:
  contents: write
jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Lingo.dev
        uses: lingodotdev/lingo.dev@main
        with:
          api-key: ${{ secrets.LINGODOTDEV_API_KEY }}

GitHub リポジトリの Settings > Secrets and variables > Actions で、API key を LINGODOTDEV_API_KEY として保存してください。

デプロイ前に確認する#

未翻訳のコンテンツが本番環境に出ないよう、デプロイゲートとして --frozen フラグを使ってください。翻訳が必要なエントリが 1 つでもあれば、CLI は非ゼロステータスで終了します。

bash
npx lingo.dev@latest run --frozen

これを Next.js の build 前に実行する、独立した CI ステップとして追加します。

yaml
- name: Verify translations
  run: npx lingo.dev@latest run --frozen
- name: Build
  run: pnpm build

次のステップ#

Static Content Localization
Markdown、MDX、JSON、YAML など、さまざまなバケットタイプに対応
Web App Localization
主要な Web フレームワークにおける UI 文字列パターン
CI/CD Workflows
GitHub Actions、GitLab CI、Bitbucket Pipelines の実践パターン
Glossaries
ブランド名や技術用語を翻訳されないよう固定する

このページは役に立ちましたか?

Max PrilutskiyMax Prilutskiy·更新済み 10日前·3分で読めます