国際化 (i18n)
型安全な翻訳でProductReadyアプリに多言語サポートを追加
国際化 (i18n)
ProductReadyには、typesafe-i18nを使用した組み込みのi18nサポートが付属しています。アプリに複数の言語を追加できます:
- ✅ 型安全な翻訳 - すべての翻訳キーのオートコンプリート
- ✅ 英語 + 中国語 + 日本語がすぐに使える
- ✅ 新しい言語の追加が簡単 - 翻訳ファイルを追加するだけ
- ✅ どこでも機能 - サーバーコンポーネント、クライアントコンポーネント、APIルート
ランタイムオーバーヘッドゼロ: すべての翻訳はコンパイル時にチェックされ、ツリーシェイクされます!
クイックスタート
多言語コンテンツを表示
ProductReadyのURLには言語プレフィックスが含まれます:
http://localhost:3000/en ← 英語
http://localhost:3000/zh-CN ← 中国語
http://localhost:3000/ja ← 日本語ドキュメントは完全に翻訳されています:
http://localhost:3000/en/docs
http://localhost:3000/zh-CN/docs
http://localhost:3000/ja/docs仕組み
URL構造
/[lang]/(home)/page.tsx ← ランディングページ(すべての言語)
/[lang]/docs/[[...slug]]/page.tsx ← ドキュメント(すべての言語)Next.jsは自動的に:
[lang]セグメントを検出- 正しい翻訳を読み込み
- ローカライズされたコンテンツをレンダリング
言語検出メカニズム
ProductReadyは、コンテキストに応じて2つの異なる言語検出戦略を使用します:
Webページ(マーケティング、ドキュメント、認証)
/、/docs、/pricing、/sign-inなどのURLベースのルートでは、ミドルウェアは次の優先順位を使用します:
| 優先順位 | ソース | 説明 |
|---|---|---|
| 1 | URLプレフィックス | /zh-CN/docs → 中国語 |
| 2 | Cookie(webpage_lang) | リピーター訪問者 |
| 3 | Accept-Languageヘッダー | 初回訪問者(ブラウザ設定) |
| 4 | デフォルトロケール | enへのフォールバック |
ユーザーがページを訪問すると:
- URLに言語プレフィックスがある場合 → その言語を使用し、Cookieを設定
- プレフィックスはないがCookieが存在する場合 → 優先言語にリダイレクト
- 初回訪問者の場合 → ブラウザのAccept-Languageヘッダーから検出
- それ以外 → デフォルトロケール(英語)を使用
Cookieは1年間保持されるため、リピーター訪問者は優先言語が表示されます。
SPAページ(ダッシュボード、エージェント、スペース)
/dashboard、/agent、/spaces/*などのダッシュボードルートでは、LocaleProviderは次の優先順位を使用します:
| 優先順位 | ソース | 説明 |
|---|---|---|
| 1 | ユーザーDB設定 | データベースのuser.locale |
| 2 | localStorage(app_locale) | クライアント側の設定 |
| 3 | ブラウザ言語 | navigator.languages検出 |
| 4 | デフォルトロケール | enへのフォールバック |
Webページとの主な違い:
- URLプレフィックスなし - ダッシュボードルートに
/zh-CN/dashboardはありません - ユーザー設定が最優先 - ログインユーザーのDB設定が優先
- localStorage永続化 - SPAナビゲーションではCookieより高速
- クライアント側検出 -
@formatjs/intl-localematcherを使用してブラウザ言語マッチング
コンポーネントで翻訳を使用
クライアントコンポーネント
'use client';
import { useI18nContext } from '~/i18n/i18n-react';
export function WelcomeMessage() {
const { LL } = useI18nContext();
return (
<div>
<h1>{LL.common.appName()}</h1>
<p>{LL.common.tagline()}</p>
</div>
);
}サーバーコンポーネント
import { loadLocale } from '~/i18n/i18n-util.sync';
import type { Locales } from '~/i18n/i18n-types';
export default async function ServerPage({
params
}: {
params: { lang: Locales }
}) {
const LL = loadLocale(params.lang);
return (
<div>
<h1>{LL.common.appName()}</h1>
<p>{LL.common.tagline()}</p>
</div>
);
}新しい言語を追加
ステップ 1: サポートされる言語を追加
src/lib/i18n/config.tsを編集:
export const SUPPORTED_LOCALES = ["en", "zh-CN", "ja", "ko"] as const;
// ^^^^ 新しい言語
export const LOCALE_DISPLAY_NAMES: Record<Locale, string> = {
en: "English",
"zh-CN": "简体中文",
ja: "日本語",
ko: "한국어", // 追加
};
export const AUTO_LABEL: Record<Locale, string> = {
en: "Auto",
"zh-CN": "自动",
ja: "自動",
ko: "자동", // 追加
};ステップ 2: 翻訳ファイルを作成
src/i18n/ko/index.tsを作成:
import type { Translation } from '../i18n-types';
const ko: Translation = {
common: {
appName: "ProductReady",
tagline: "장난감 코드를 판매 가능한 제품으로 전환",
loading: "로딩 중...",
error: "오류",
success: "성공",
// ... 他のすべての翻訳
},
// ... 他のすべてのセクション
};
export default ko;ステップ 3: ドキュメントを追加(オプション)
content/docs/ko/にドキュメントを作成:
content/docs/ko/
├── index.mdx
├── quick-start.mdx
└── meta.jsonステップ 4: テスト
pnpm devhttp://localhost:3000/koを訪問
翻訳キーを追加
ステップ 1: 英語翻訳を追加
src/i18n/en/index.tsを編集:
const en = {
common: {
// ... 既存の翻訳
newKey: "New Translation",
},
};ステップ 2: 他の言語を更新
src/i18n/zh-CN/index.ts、src/i18n/ja/index.tsを同じキーで更新:
const zhCN = {
common: {
// ... 既存の翻訳
newKey: "新的翻译",
},
};
const ja = {
common: {
// ... 既存の翻訳
newKey: "新しい翻訳",
},
};ステップ 3: 型を生成
pnpm i18n:typegenステップ 4: 使用
const { LL } = useI18nContext();
<p>{LL.common.newKey()}</p>動的な翻訳
変数付きの翻訳
// 翻訳ファイル
const en = {
greeting: "Hello, {name}!",
};
// コンポーネント内
<p>{LL.greeting({ name: "Alice" })}</p>
// → "Hello, Alice!"複数形の処理
const en = {
itemCount: "{count|plural|one:1 item|other:{count} items}",
};
<p>{LL.itemCount({ count: 1 })}</p> // → "1 item"
<p>{LL.itemCount({ count: 5 })}</p> // → "5 items"ベストプラクティス
翻訳の整理
- ✅ 機能でグループ化:
auth.signIn、auth.signUp - ✅ 一貫した命名:動詞-名詞パターンを使用
- ✅ キーを短く保つ:
common.save(common.saveButtonではなく) - ❌ 深くネストしすぎない:3レベルまで
翻訳の品質
- ✅ ネイティブスピーカーを使用:機械翻訳を避ける
- ✅ コンテキストを提供:翻訳者がキーの使用場所を理解できるようにする
- ✅ 定期的にレビュー:翻訳を最新の状態に保つ
- ✅ テスト:すべての言語が正しく表示されることを確認
トラブルシューティング
翻訳が表示されない
問題:翻訳キーがそのまま表示される。
解決策:
pnpm i18n:typegenを実行して型を生成- すべての言語で翻訳キーが定義されていることを確認
- サーバーを再起動
型エラー
問題:TypeScriptが翻訳キーを認識しない。
解決策:
pnpm i18n:typegenを実行- TypeScriptサーバーを再起動(VSCode:
Cmd+Shift+P→ "Reload Window")
次のステップ
i18nを設定したので:
- ドキュメントシステム - 多言語ドキュメントを追加
- デザインシステム - RTL言語のスタイル
- SEO - 多言語SEOを最適化
参考資料
ProductReadyで国際化を楽しんでください! 🌍