# 機能設計書 70-CMS UIローカライズ

## 概要

本ドキュメントは、Decap CMSのCMS UIローカライズ機能の設計を定義する。本機能は、CMS管理画面UIの30以上の言語へのローカライズを実現し、カスタムロケールの登録もサポートする。

### 本機能の処理概要

CMS UIローカライズ機能は、Decap CMSの管理画面インターフェースを多言語で表示するための機能である。decap-cms-localesパッケージに各言語の翻訳フレーズが定義され、レジストリのregisterLocale/getLocale APIを通じてロケールデータの登録・取得を行う。

**業務上の目的・背景**：Decap CMSは世界中で使用されるオープンソースCMSであり、英語以外の言語で管理画面を使用したいニーズがある。UIテキスト（ボタンラベル、メッセージ、ツールチップ等）をローカライズすることで、非英語圏のコンテンツ編集者の利便性を向上させる。

**機能の利用シーン**：CMS設定ファイル（config.yml）のlocaleフィールドで言語を指定すると、対応する翻訳フレーズが適用される。また、CMS.registerLocale()で独自の翻訳フレーズを追加・上書きできる。

**主要な処理内容**：
1. 34言語のロケールデータパッケージの提供
2. registerLocale(locale, phrases)によるロケールの登録
3. getLocale(locale)によるロケールデータの取得
4. 翻訳キーのネスト構造による階層的なフレーズ管理
5. %{variable}形式のプレースホルダーによる動的テキスト
6. smart_countによる複数形対応（||||区切り）

**関連システム・外部連携**：レジストリ（registry.js）のlocalesオブジェクトと連携。各コンポーネントはt()関数を通じて翻訳フレーズにアクセスする。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | 404 Not Found画面 | 参照画面 | t('app.notFoundPage.header')による404ページヘッダーのローカライズ |
| 12 | ローディング画面 | 参照画面 | t('app.app.loadingConfig')によるローディングメッセージのローカライズ |

## 機能種別

UIローカライズ / 翻訳管理

## 入力仕様

### 入力パラメータ

#### registerLocale

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| locale | string | Yes | ロケールコード（例: 'ja', 'en', 'de'） | 空文字不可 |
| phrases | object | Yes | 翻訳フレーズオブジェクト | 空オブジェクト不可 |

#### getLocale

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| locale | string | Yes | ロケールコード | - |

### 入力データソース

- decap-cms-localesパッケージ: 各言語の翻訳フレーズ定義
- CMS API: CMS.registerLocale()による動的登録

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| phrases | object | ネスト構造の翻訳フレーズオブジェクト |

### 出力先

- レジストリ: registry.localesオブジェクトに格納
- UIコンポーネント: t()関数経由でローカライズされたテキストを表示

## 処理フロー

### 処理シーケンス

```
1. ロケール登録
   ├─ decap-cms-default-exportsで標準ロケールをバルク登録
   └─ CMS.registerLocale()でカスタムロケールを登録
2. CMS設定読込
   └─ config.ymlのlocaleフィールドからロケールコードを取得
3. ロケール取得
   └─ getLocale(locale)でregistry.localesからフレーズオブジェクトを取得
4. 翻訳適用
   └─ t()関数で翻訳キー（例: 'editor.editorToolbar.save'）からフレーズを解決
5. 動的テキスト
   └─ %{variable}プレースホルダーをコンテキスト値で置換
```

### フローチャート

```mermaid
flowchart TD
    A[CMS初期化] --> B[registerLocale - 標準ロケール登録]
    B --> C[config.yml読込]
    C --> D[locale設定取得]
    D --> E[getLocale - フレーズ取得]
    E --> F["t('key') - 翻訳解決"]
    F --> G{プレースホルダー?}
    G -->|Yes| H["%{var}を値で置換"]
    G -->|No| I[フレーズをそのまま表示]
    H --> J[UI表示]
    I --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-70-01 | ロケール登録バリデーション | localeまたはphrasesが空の場合、console.errorでエラーメッセージを出力して登録をスキップ | registerLocale呼び出し時 |
| BR-70-02 | 上書き可能 | 同名のロケールを再登録すると上書きされる | 既存ロケールコードで再登録時 |
| BR-70-03 | 翻訳キー構造 | ドット区切りの階層キー（例: 'editor.editorToolbar.save'）でネストオブジェクトにアクセス | t()関数使用時 |
| BR-70-04 | プレースホルダー | %{variableName}形式で動的値を埋め込み | フレーズに%{...}が含まれる場合 |
| BR-70-05 | 複数形 | smart_countパラメータと'||||'区切りで単数形・複数形を切替 | smart_countが指定された場合 |

### 計算ロジック

特になし。

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

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

該当なし（メモリ上のグローバルレジストリへの登録のみ）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 不正なパラメータ | localeまたはphrasesが未指定 | console.errorで"Locale parameters invalid"メッセージ出力、登録をスキップ |
| - | 未登録ロケール | getLocaleで未登録のロケールコードが指定された場合 | undefinedを返却（英語フォールバックは呼出側で対応） |

### リトライ仕様

リトライ処理は行わない。

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

該当なし。

## パフォーマンス要件

- ロケールデータはオブジェクトとしてメモリに保持されるため、アクセスは高速
- 各言語パッケージは遅延読込ではなく、使用言語のみインポートする構成

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

- 翻訳フレーズはHTMLとしてレンダリングされる場合があるため、XSSに注意（React標準のエスケープで対応）
- registerLocaleはCMS初期化時にのみ呼び出される前提

## 備考

- decap-cms-localesパッケージは34言語（cs, da, de, en, es, ca, fr, fa, gr, hu, it, lt, ja, nl, nb_no, nn_no, pl, pt, ro, ru, sv, th, tr, uk, vi, zh_Hant, ko, hr, sl, bg, mk, zh_Hans, he, ua）をサポート
- 英語（en）が基準ロケールであり、他の言語はenの構造に準じて翻訳フレーズを定義

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | en/index.js | `packages/decap-cms-locales/src/en/index.js` | 英語ロケールの完全な翻訳フレーズ構造。auth, app, collection, editor, mediaLibrary, ui, workflowの7つのトップレベルカテゴリ |

**読解のコツ**: 翻訳フレーズは階層的なJavaScriptオブジェクトとして定義される。キーはドット区切りのパスでアクセスされる（例: `editor.editorToolbar.save` → `'Save'`）。`%{variableName}`はプレースホルダー、`||||`は複数形区切り。

#### Step 2: ロケールパッケージのエクスポートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `packages/decap-cms-locales/src/index.js` | 34言語のnamed exportによるバルクエクスポート |

**主要処理フロー**:
- **1-34行目**: 各言語ディレクトリのdefaultエクスポートをnamed exportとして再エクスポート

#### Step 3: レジストリのロケール管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | registry.js | `packages/decap-cms-core/src/lib/registry.js` | registerLocale/getLocaleのAPI定義 |

**主要処理フロー**:
- **32行目**: `registry.locales = {}`で初期化
- **277-283行目**: registerLocale - localeとphrasesの検証後、registry.locales[locale]に登録
- **285-287行目**: getLocale - registry.locales[locale]を返却

#### Step 4: 翻訳フレーズの構造を理解する

英語ロケールの主要カテゴリ:
- `auth`: 認証関連（ログインボタン、エラーメッセージ）
- `app`: アプリケーション全般（ヘッダー、エラー画面、Not Found）
- `collection`: コレクション関連（サイドバー、ソート、フィルタ）
- `editor`: エディタ関連（ツールバー、ウィジェット、i18n）
- `mediaLibrary`: メディアライブラリ関連
- `ui`: 汎用UI（エラーバウンダリ、トースト通知）
- `workflow`: ワークフロー関連（カンバンボード）

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

```
decap-cms-locales/src/index.js
    ├─ en/index.js → 英語フレーズ
    ├─ ja/index.js → 日本語フレーズ
    ├─ de/index.js → ドイツ語フレーズ
    └─ ... (34言語)

registry.js
    ├─ registerLocale(locale, phrases)
    │   └─ registry.locales[locale] = phrases
    │
    └─ getLocale(locale)
        └─ return registry.locales[locale]

UIコンポーネント
    └─ t('editor.editorToolbar.save')
        └─ getLocale(currentLocale)
            └─ phrases.editor.editorToolbar.save → 'Save' / '保存' / etc.
```

### データフロー図

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

ロケールパッケージ ──────▶ registerLocale()
  (decap-cms-locales)          │
                              ▼
config.yml ─────────────▶ locale設定取得
  (locale: 'ja')               │
                              ▼
翻訳キー ──────────────▶ getLocale(locale) → t(key)
  ('editor.editorToolbar.save')    │
                                  ▼
                            ローカライズされたテキスト ──▶ UI表示
                              ('保存')
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `packages/decap-cms-locales/src/index.js` | ソース | ロケールパッケージのバルクエクスポート |
| en/index.js | `packages/decap-cms-locales/src/en/index.js` | ソース | 英語ロケール（基準） |
| ja/index.js | `packages/decap-cms-locales/src/ja/index.js` | ソース | 日本語ロケール |
| de/index.js | `packages/decap-cms-locales/src/de/index.js` | ソース | ドイツ語ロケール |
| registry.js | `packages/decap-cms-core/src/lib/registry.js` | ソース | registerLocale/getLocale API |
