# 機能設計書 75-国際化対応

## 概要

本ドキュメントは、Etherpadにおける国際化（i18n）対応機能の設計を定義する。多言語対応のための翻訳処理とロケール管理について記述する。

### 本機能の処理概要

Etherpadの画面表示を複数の言語で提供するための国際化機能である。サーバーサイドでのロケールファイル管理とクライアントサイドでの動的言語切り替えを実現する。

**業務上の目的・背景**：Etherpadはグローバルに利用されるオープンソースプロジェクトであり、世界中のユーザーが母国語でアプリケーションを使用できることが重要である。本機能により、105言語以上の翻訳を提供し、ユーザーエクスペリエンスを向上させる。また、プラグインも同一のメカニズムで多言語対応が可能となる。

**機能の利用シーン**：
- ユーザーがブラウザの言語設定に基づいて画面を表示
- パッド設定画面での言語切り替え
- プラグインの翻訳文字列の適用
- 管理者によるカスタム翻訳文字列の追加

**主要な処理内容**：
1. ロケールファイル（JSON形式）の読み込みと集約
2. プラグインのロケールファイルとのマージ
3. カスタムロケール文字列（settings.json）の適用
4. 言語別ロケールインデックスの生成
5. /locales/:locale エンドポイントでの言語データ配信
6. クライアントサイドでのhtml10nによる動的翻訳

**関連システム・外部連携**：languages4translatewikiライブラリ（言語コード検証）、html10n（クライアント側翻訳）を使用。

**権限による制御**：言語設定は全ユーザーが変更可能。カスタム翻訳の追加は管理者のみ。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | トップページ | 補助機能 | 画面表示の多言語対応処理 |
| 2 | パッド編集画面 | 補助機能 | 言語設定で表示言語を切り替え |
| 3 | タイムスライダー画面 | 補助機能 | 画面表示の多言語対応処理 |
| 7 | プラグイン管理画面 | 補助機能 | 管理画面の多言語対応 |
| 8 | 設定管理画面 | 補助機能 | 設定画面の多言語対応 |

## 機能種別

国際化 / ローカライゼーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| locale | string | Yes（API用） | 言語コード（例：ja、en、de） | languages4translatewikiで検証 |
| customLocaleStrings | object | No | カスタム翻訳文字列 | settings.jsonで定義 |

### 入力データソース

- src/locales/*.json: コアの翻訳ファイル
- プラグイン/locales/*.json: プラグインの翻訳ファイル
- settings.json customLocaleStrings: カスタム翻訳

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| locales | object | 言語コードをキーとした翻訳文字列のマップ |
| availableLangs | object | 利用可能な言語の一覧（nativeName、direction含む） |

### 出力先

- /locales.json: 言語インデックス
- /locales/:locale: 言語別翻訳データ
- HTML data-l10n-id属性: クライアント側での翻訳適用

## 処理フロー

### 処理シーケンス

```
1. ロケールファイル収集
   └─ src/locales/配下のJSONファイルを読み込み
2. プラグインロケール追加
   └─ 各プラグインのlocales/配下のJSONファイルを読み込み
3. ロケールマージ
   └─ 同一言語のファイルをマージ
4. カスタム文字列適用
   └─ settings.customLocaleStringsで上書き
5. インデックス生成
   └─ locales.jsonを生成
6. API提供
   └─ /locales/:localeでJSON配信
```

### フローチャート

```mermaid
flowchart TD
    A[サーバー起動] --> B[extractLangs - コアロケール読み込み]
    B --> C[extractLangs - プラグインロケール読み込み]
    C --> D[言語別にファイルをマージ]
    D --> E{customLocaleStrings設定あり?}
    E -->|Yes| F[カスタム文字列で上書き]
    E -->|No| G[localesオブジェクト完成]
    F --> G
    G --> H[generateLocaleIndex]
    H --> I[/locales/:locale 配信準備完了]
    I --> J[クライアントリクエスト]
    J --> K{言語コード有効?}
    K -->|Yes| L[JSON レスポンス]
    K -->|No| M[404 Language not available]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-75-01 | 言語コード検証 | languages4translatewikiで有効性を検証 | ロケールファイル読み込み時 |
| BR-75-02 | プラグイン優先 | プラグインのロケールがコアを上書き | 同一キーが存在する場合 |
| BR-75-03 | カスタム最優先 | customLocaleStringsが全てを上書き | 設定が存在する場合 |
| BR-75-04 | 英語基準 | locales.jsonでは英語をベースに他言語のパスを格納 | インデックス生成時 |
| BR-75-05 | キャッシュ制御 | maxAge設定に基づいてCache-Controlヘッダー設定 | APIレスポンス時 |
| BR-75-06 | RTL対応 | 右から左に読む言語を識別 | ar、he、fa等のRTL言語 |

### 計算ロジック

特になし

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

本機能ではデータベース操作は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | 無効な言語コード | "Language not available" |
| - | Error | 無効なcustomLocaleStrings形式 | 起動時エラー |
| - | Error | 不正なJSON形式のロケールファイル | コンソールエラー出力 |

### リトライ仕様

なし

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

なし

## パフォーマンス要件

- ロケールデータはサーバー起動時に一度だけ読み込み
- クライアントへのレスポンスはキャッシュ可能
- 言語数に関わらず一定時間で起動

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

- ロケールファイルのパスはプラグインディレクトリ内に限定
- customLocaleStringsの値はサニタイズされないため、XSS対策が必要な場合は別途対応
- ファイルシステムアクセスはシンボリックリンクを除外

## 備考

- TranslateWiki（https://translatewiki.net/）で翻訳が管理されている
- 新しい翻訳キーを追加する場合はsrc/locales/en.jsonに追加
- プラグインはlocales/ディレクトリに同様の形式でファイルを配置

---

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

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

### 推奨読解順序

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

ロケールデータの構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | en.json | `src/locales/en.json` | 翻訳キーと値の形式 |
| 1-2 | Settings.ts | `src/node/utils/Settings.ts` | customLocaleStringsの型定義 |

**読解のコツ**: ロケールファイルはフラットなキー・値のJSONオブジェクト。キーはドット区切りで階層を表現。

#### Step 2: エントリーポイントを理解する

Expressルーティングとロケール初期化を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | i18n.ts | `src/node/hooks/i18n.ts` | expressPreSession hookの実装 |

**主要処理フロー**:
1. **126-149行目**: expressPreSession hookの全体
2. **128行目**: getAllLocales()でロケールデータ収集
3. **129行目**: generateLocaleIndex()でインデックス生成
4. **130行目**: getAvailableLangs()で利用可能言語取得
5. **132-148行目**: Express APIエンドポイント登録

#### Step 3: ロケール収集処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | i18n.ts | `src/node/hooks/i18n.ts` | getAllLocales関数 |

**主要処理フロー**:
- **16-104行目**: getAllLocales関数の全体
- **22-40行目**: extractLangs内部関数（ディレクトリからロケールファイル抽出）
- **43行目**: コアロケール読み込み（src/locales）
- **46-50行目**: プラグインロケール読み込み
- **53-67行目**: ファイルをマージしてlocalesオブジェクト構築
- **74-101行目**: customLocaleStrings適用

#### Step 4: クライアント側翻訳を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | html10n.ts | `src/static/js/vendors/html10n.ts` | Html10nクラス |

**主要処理フロー**:
- **6-52行目**: Html10nクラスの基本構造
- **22-46行目**: pluralマクロの実装（複数形対応）
- **72-200行目以降**: getPluralRules関数（言語別複数形ルール）

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

```
Expressアプリケーション起動
    │
    └─ i18n.ts (expressPreSession hook)
           │
           ├─ getAllLocales() [16-104行目]
           │      ├─ extractLangs(src/locales) [43行目]
           │      ├─ extractLangs(plugin/locales) [46-50行目]
           │      └─ customLocaleStrings適用 [74-101行目]
           │
           ├─ generateLocaleIndex() [117-123行目]
           │
           └─ getAvailableLangs() [108-114行目]

クライアント側
    │
    └─ html10n.ts
           ├─ index() - DOM走査と翻訳適用
           ├─ get() - 翻訳文字列取得
           └─ getPluralRules() - 複数形ルール取得
```

### データフロー図

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

src/locales/*.json ─────▶ extractLangs() ─────▶ locales2paths Map
                                 │
plugins/locales/*.json ──▶ extractLangs() ─────▶ locales2paths Map
                                 │
                                 ▼
                         ファイル読み込み・マージ
                                 │
settings.customLocaleStrings ───▶│
                                 ▼
                          localesオブジェクト
                                 │
                    ┌────────────┴────────────┐
                    ▼                         ▼
         generateLocaleIndex()     getAvailableLangs()
                    │                         │
                    ▼                         ▼
            /locales.json            availableLangs
                                              │
                                              ▼
                                    /locales/:locale
                                              │
                                              ▼
                                    html10n (クライアント)
                                              │
                                              ▼
                                    DOM翻訳適用
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| i18n.ts | `src/node/hooks/i18n.ts` | ソース | サーバーサイドのロケール管理 |
| html10n.ts | `src/static/js/vendors/html10n.ts` | ソース | クライアントサイドの翻訳適用 |
| en.json | `src/locales/en.json` | ロケール | 英語（基準言語）の翻訳ファイル |
| ja.json | `src/locales/ja.json` | ロケール | 日本語の翻訳ファイル |
| Settings.ts | `src/node/utils/Settings.ts` | ソース | customLocaleStrings設定 |
| pad.html | `src/templates/pad.html` | テンプレート | data-l10n-id属性を使用 |
| index.html | `src/templates/index.html` | テンプレート | data-l10n-id属性を使用 |
