# 機能設計書 37-多言語対応（i18n）

## 概要

本ドキュメントは、Ghostの多言語対応（Internationalization/i18n）機能に関する設計仕様を定義する。この機能により、サイトのUI文言を60以上の言語で表示し、テーマの翻訳にも対応する。

### 本機能の処理概要

多言語対応機能は、i18nextライブラリを使用してGhostの各種UIコンポーネント（Portal、Comments、Signup Form、Search）およびテーマの翻訳を管理する機能である。翻訳ファイルはJSONフォーマットで管理され、名前空間（namespace）によって分類される。

**業務上の目的・背景**：グローバルなユーザーベースに対応し、母国語でのサイト閲覧を可能にする。多言語対応により、非英語圏のユーザーもGhostを快適に利用でき、サイトのアクセシビリティと利用者層を拡大できる。

**機能の利用シーン**：
- 日本語のブログサイトを構築する場合
- 多言語サイトを運営する場合
- テーマ独自の翻訳文言を定義する場合
- フロントエンドウィジェット（Portal、Comments等）を現地語で表示する場合

**主要な処理内容**：
1. サイトのlocale設定に基づく言語の決定
2. 名前空間別の翻訳リソースの読み込み
3. i18nextインスタンスの初期化と設定
4. テーマ用翻訳ファイルの読み込み
5. 翻訳キーに対応する文言の返却

**関連システム・外部連携**：
- i18next：国際化フレームワーク
- Portal/Comments UI/Signup Form/Sodo Search：フロントエンドウィジェット
- テーマエンジン：テーマ翻訳

**権限による制御**：言語設定は管理者（Administrator）以上が変更可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | 言語設定 | 主画面 | サイトの表示言語設定 |

## 機能種別

設定管理 / 翻訳処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| locale | String | Yes | 言語コード（例：ja, en, de） | SUPPORTED_LOCALESに含まれること |

### 入力データソース

- settingsテーブルのlocale設定
- テーマのlocalesディレクトリ（`{theme}/locales/{locale}.json`）
- ghost/i18nパッケージの翻訳ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 翻訳文言 | String | キーに対応する翻訳済みテキスト |

### 出力先

- フロントエンドUI（Portal、Comments、Signup Form、Search）
- テーマテンプレート

## 処理フロー

### 処理シーケンス

```
1. i18nインスタンスの生成
   └─ 言語コード（lng）と名前空間（ns）を指定
   └─ 翻訳リソースの生成
   └─ i18next.init()で初期化

2. 翻訳リソースの生成
   └─ SUPPORTED_LOCALESをループ
   └─ 各言語の翻訳ファイルを読み込み
   └─ 存在しない場合は英語にフォールバック

3. テーマ翻訳の読み込み
   └─ テーマのlocalesディレクトリをスキャン
   └─ 指定言語のJSONファイルを読み込み
   └─ 存在しない場合は英語にフォールバック

4. 翻訳の実行
   └─ t(key)で翻訳キーを渡す
   └─ 対応する翻訳文言を返却
```

### フローチャート

```mermaid
flowchart TD
    A[i18n初期化] --> B{名前空間?}
    B -->|theme| C[テーマ翻訳読み込み]
    B -->|その他| D[パッケージ翻訳読み込み]
    C --> E[localesディレクトリスキャン]
    E --> F{翻訳ファイル存在?}
    F -->|Yes| G[JSONファイル読み込み]
    F -->|No| H[英語にフォールバック]
    D --> I[locales/{lng}/{ns}.json読み込み]
    I --> J{ファイル存在?}
    J -->|Yes| K[リソースに追加]
    J -->|No| L[英語にフォールバック]
    G --> M[i18next.init()]
    H --> M
    K --> M
    L --> M
    M --> N[翻訳インスタンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | フォールバック言語 | 翻訳が見つからない場合は英語（en）にフォールバック | 翻訳キー検索時 |
| BR-37-02 | ノルウェー語フォールバック | noはnb（ノルウェーブークモール）にフォールバック | no言語指定時 |
| BR-37-03 | 空文字の扱い | 空文字の場合はキーをそのまま返却 | returnEmptyString: false |
| BR-37-04 | 名前空間分離 | ghost, portal, comments, search, signup-form, themeの名前空間で翻訳を分離 | 翻訳読み込み時 |
| BR-37-05 | キャッシュクリア | テーマ翻訳は毎回requireキャッシュをクリアして読み込み | テーマ翻訳時 |

### 計算ロジック

- 補間: `{variable}` 形式でプレースホルダーを置換（prefix: '{', suffix: '}'）
- テーマ翻訳ではHTMLエスケープなし（escapeValue: false）

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| locale取得 | settings | SELECT | サイトの言語設定を取得 |

### ファイル操作詳細

| 操作 | ファイル | 処理内容 | 備考 |
|-----|---------|---------|------|
| 読み込み | ghost/i18n/locales/{lng}/{ns}.json | パッケージ翻訳の読み込み | 名前空間別 |
| 読み込み | {theme}/locales/{lng}.json | テーマ翻訳の読み込み | テーマ別 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IncorrectUsageError | 翻訳ファイルが見つからない | 英語にフォールバック、デバッグログ出力 |

### リトライ仕様

リトライは不要。フォールバック機構により翻訳は必ず返却される。

## トランザクション仕様

データベーストランザクションは不要（ファイルベース）。

## パフォーマンス要件

- 翻訳リソースは起動時に読み込まれ、メモリ上に保持
- テーマ翻訳のみ動的に読み込み（requireキャッシュクリア）

## セキュリティ考慮事項

- テーマ翻訳ではHTMLエスケープが無効のため、信頼できるテーマのみ使用
- 翻訳ファイルはサーバーサイドで管理

## 備考

- サポートされる言語は64言語（LOCALE_DATAで定義）
- 各名前空間の用途：
  - ghost: 管理画面（Admin）
  - portal: 会員ポータルUI
  - comments: コメントUI
  - search: 検索UI
  - signup-form: サインアップフォーム
  - theme: テーマ固有翻訳

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、言語データと翻訳ファイルの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | locale-data.json | `ghost/i18n/lib/locale-data.json` | **1-64行目**: サポート言語リスト（code, label） |
| 1-2 | ja/portal.json等 | `ghost/i18n/locales/ja/*.json` | 翻訳ファイルの構造（キー: 翻訳文言） |

**読解のコツ**:
- locale-data.jsonで64言語のコードとラベルを確認
- 各localeディレクトリに名前空間別のJSONファイルがある

#### Step 2: i18nモジュールを理解する

メインのi18n初期化ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | i18n.js | `ghost/i18n/lib/i18n.js` | **1-155行目**: i18nモジュール全体 |

**主要処理フロー**:
1. **13-31行目**: `generateResources()` - パッケージ翻訳リソースの生成
2. **33-101行目**: `generateThemeResources()` - テーマ翻訳リソースの生成
3. **107-150行目**: モジュールエクスポート関数 - i18nextインスタンスの初期化

#### Step 3: 設定との連携を理解する

locale設定の取得方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | default-settings.json | `ghost/core/core/server/data/schema/default-settings/default-settings.json` | **122-128行目**: locale設定（デフォルト: "en"） |

#### Step 4: フロントエンド利用を理解する

フロントエンドウィジェットでのi18n利用方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | 各アプリのi18n利用 | `apps/portal/`, `apps/comments-ui/`等 | i18nextインスタンスの利用方法 |

### プログラム呼び出し階層図

```
i18n モジュール呼び出し
    │
    └─ i18n(lng, ns, options)
           │
           ├─ (ns !== 'theme')
           │      └─ generateResources(SUPPORTED_LOCALES, ns)
           │             │
           │             ├─ require(`../locales/${locale}/${ns}.json`)
           │             │
           │             └─ (失敗時) require(`../locales/en/${ns}.json`)
           │
           ├─ (ns === 'theme')
           │      └─ generateThemeResources(lng, themePath)
           │             │
           │             ├─ fs.readdirSync(themeLocalesPath)
           │             │
           │             ├─ require(localePath)
           │             │
           │             └─ (失敗時) require(enPath)
           │
           └─ i18nextInstance.init({
                  lng,
                  fallbackLng: {no: ['nb', 'en'], default: ['en']},
                  ns,
                  interpolation: {prefix: '{', suffix: '}'},
                  resources
              })
                  │
                  └─ i18nextInstance (翻訳可能インスタンス)
```

### データフロー図

```
[入力]                    [処理]                           [出力]

locale設定 ──────────▶ i18n(lng, ns)
                              │
                              ▼
                        翻訳リソース生成
                              │
                        ┌─────┴─────┐
                        ▼           ▼
                   パッケージ    テーマ
                    翻訳        翻訳
                        │           │
                        ▼           ▼
                        i18next初期化
                              │
                              ▼
                        t(key) 呼び出し
                              │
                              ▼
                        翻訳文言 ───────▶ UI表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| i18n.js | `ghost/i18n/lib/i18n.js` | ソース | i18nメインモジュール |
| locale-data.json | `ghost/i18n/lib/locale-data.json` | 設定 | サポート言語リスト |
| locales/ | `ghost/i18n/locales/` | 翻訳 | 各言語・名前空間の翻訳ファイル |
| theme-i18n.js | `ghost/core/core/frontend/services/theme-engine/i18n/theme-i18n.js` | ソース | テーマi18n統合 |
| default-settings.json | `ghost/core/core/server/data/schema/default-settings/default-settings.json` | 設定 | locale設定定義 |
