# 機能設計書 79-多言語対応

## 概要

本ドキュメントは、Lua Language Serverにおける多言語対応（国際化/i18n）機能の設計を記述する。この機能は、ユーザーインターフェースのメッセージを複数の言語で表示できるようにし、世界中の開発者が母国語でサーバーを利用できるようにする。

### 本機能の処理概要

**業務上の目的・背景**：Lua Language Serverはグローバルに利用されるため、エラーメッセージ、診断情報、ホバー情報などを複数の言語で表示する必要がある。本機能は言語ファイルの管理と動的なメッセージ取得を提供し、英語、中国語（簡体字/繁体字）、日本語、ポルトガル語、スペイン語などの言語をサポートする。

**機能の利用シーン**：
- サーバー起動時の言語設定
- 診断メッセージの表示
- ホバー情報の表示
- エディタへの通知メッセージ
- CLI出力メッセージ

**主要な処理内容**：
1. 言語ファイル（script.lua, meta.lua, setting.lua）の読み込み
2. 言語IDからの言語解決
3. メッセージテンプレートの変数展開
4. フォールバック言語（英語）への自動切り替え
5. 未定義キーの自動追加

**関連システム・外部連携**：
- LSPクライアント（言語設定）
- ファイルシステム（言語ファイル読み込み）
- すべてのメッセージ出力モジュール

**権限による制御**：特になし。すべてのユーザーが言語を選択可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は全画面で使用される基盤機能 |

## 機能種別

国際化 / メッセージ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --locale | string | No | 言語ID（例: ja-jp, zh-cn） | サポート言語のいずれか |
| id | string | Yes | 言語ID（モジュール呼び出し時） | - |
| key | string | Yes | メッセージキー | - |
| ... | any | No | テンプレート変数 | - |

### 入力データソース

- locale/ディレクトリ内の言語ファイル
- LSPクライアントからの言語設定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| message | string | ローカライズされたメッセージ |

### 出力先

- 各種メッセージ出力先（診断、ホバー、通知等）

## 処理フロー

### 処理シーケンス

```
1. 言語モジュール呼び出し
   └─ lang(id)で言語設定
2. サポート言語の確認
   └─ locale/ディレクトリを走査
3. 言語ファイルの読み込み
   └─ script.lua, meta.lua, setting.lua
4. 英語ベースのマージ
   └─ 英語をベースに他言語をオーバーレイ
5. メッセージ取得
   └─ lang.script(key, ...)で取得
6. テンプレート展開
   └─ {index}や{name}を変数で置換
```

### フローチャート

```mermaid
flowchart TD
    A[言語設定: lang(id)] --> B[サポート言語確認]
    B --> C{サポート済み?}
    C -->|Yes| D[言語ID使用]
    C -->|No| E[近似言語検索]
    E --> F{近似言語あり?}
    F -->|Yes| D
    F -->|No| G[英語使用]
    D --> H[言語ファイル読み込み]
    G --> H
    H --> I[英語ベースのマージ]
    I --> J[言語テーブル作成]
    J --> K[メッセージ取得: lang.script]
    K --> L{キー存在?}
    L -->|Yes| M[テンプレート展開]
    L -->|No| N[キー自体を返却]
    M --> O[メッセージ返却]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-79-01 | デフォルト言語 | 未指定時は英語（en-us）を使用 | 言語未指定時 |
| BR-79-02 | 近似言語 | 完全一致しない場合、先頭2文字で近似言語を検索 | 完全一致なし時 |
| BR-79-03 | 英語フォールバック | 他言語にないキーは英語の値を使用 | キー未定義時 |
| BR-79-04 | キーフォールバック | 英語にもないキーはキー名自体を返却 | 完全未定義時 |

### 計算ロジック

**テンプレート展開ロジック**:
```lua
-- 配列形式: {0}, {1}, {2}...
local function formatAsArray(str, ...)
    local index = 0
    local args = {...}
    return str:gsub('%{(.-)%}', function (pat)
        local id, fmt = ...
        return ('%'..fmt):format(args[id])
    end)
end

-- テーブル形式: {name}, {count}...
local function formatAsTable(str, ...)
    local args = ...
    return str:gsub('%{(.-)%}', function (pat)
        return ('%'..fmt):format(args[id])
    end)
end
```

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

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

本機能はデータベース操作を行わない。ファイルシステムからの読み込みのみ。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 言語ファイル読込失敗 | ファイルが存在しない | 空テーブル返却 |
| - | フォーマットエラー | テンプレート展開失敗 | 警告ログ、元文字列返却 |
| - | 言語ファイル構文エラー | Lua構文エラー | エラーログ、空テーブル返却 |

### リトライ仕様

リトライは行わない。エラー時はフォールバック値を使用。

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

トランザクション管理は不要。

## パフォーマンス要件

- 言語テーブルはキャッシュされ、同一キーの2回目以降は即時応答
- 言語変更時にキャッシュをクリア

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

- 言語ファイルはLuaコードとして読み込まれるが、信頼できるソース（locale/ディレクトリ）のみ使用
- ユーザー入力は言語選択のみで、コード実行には影響しない

## 備考

- サポート言語: en-us, zh-cn, zh-tw, ja-jp, pt-br, es-419
- 各言語ディレクトリには script.lua（スクリプトメッセージ）、meta.lua（メタ情報）、setting.lua（設定説明）がある

---

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

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

### 推奨読解順序

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

言語モジュールの構造を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | language.lua | `script/language.lua` | 127-144行目: モジュールのメタテーブル設計 |

**読解のコツ**: `__index`で言語ファイルの遅延読み込み、`__call`で言語設定を行う。

#### Step 2: 言語解決を理解する

言語IDからの言語解決処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | language.lua | `script/language.lua` | 5-15行目: supportLanguage関数 |
| 2-2 | language.lua | `script/language.lua` | 17-34行目: getLanguage関数 |

**主要処理フロー**:
- **5-15行目**: locale/ディレクトリからサポート言語一覧を取得
- **17-34行目**: 言語IDを解決（完全一致→近似言語→英語）

#### Step 3: 言語ファイル読み込みを理解する

言語ファイルの読み込みとマージ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | language.lua | `script/language.lua` | 36-47行目: loadFileByLanguage関数 |
| 3-2 | language.lua | `script/language.lua` | 90-125行目: loadLang関数 |

**主要処理フロー**:
- **36-47行目**: 言語ファイルの読み込みとパース
- **90-97行目**: 英語をベースに他言語をマージ

#### Step 4: テンプレート展開を理解する

メッセージテンプレートの変数展開。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | language.lua | `script/language.lua` | 49-69行目: formatAsArray関数 |
| 4-2 | language.lua | `script/language.lua` | 71-88行目: formatAsTable関数 |

**主要処理フロー**:
- **49-69行目**: `{0}`, `{1}`形式の配列展開
- **71-88行目**: `{name}`, `{count}`形式のテーブル展開

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

```
lang(id) (言語設定)
    │
    └─ getLanguage(id)
           │
           ├─ supportLanguage()
           │      └─ fs.pairs(ROOT / 'locale')
           │
           └─ 言語ID解決（完全一致/近似/英語）

lang.script(key, ...) (メッセージ取得)
    │
    └─ loadLang('script', language)
           │
           ├─ loadFileByLanguage('script', 'en-us')
           │      └─ 英語ベース読み込み
           │
           └─ loadFileByLanguage('script', language)
                  └─ 指定言語でオーバーレイ
                         │
                         └─ メタテーブル__call
                                │
                                ├─ formatAsArray(str, ...)
                                │
                                └─ formatAsTable(str, ...)
```

### データフロー図

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

lang(id) ─────────────▶ getLanguage() ─────────────▶ 言語ID設定
                              │
                              ▼
lang.script ──────────▶ loadLang() ────────────────▶ 言語テーブル
                              │
                              ▼
                        英語ベース + 指定言語マージ
                              │
                              ▼
lang.script(key, ...) ▶ メタテーブル__call ─────────▶ ローカライズ
                              │                      メッセージ
                              ▼
                        formatAsArray/Table
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| language.lua | `script/language.lua` | ソース | 多言語対応のメインモジュール |
| locale-loader.lua | `script/locale-loader.lua` | ソース | 言語ファイルのロード処理 |
| script.lua | `locale/en-us/script.lua` | 言語ファイル | 英語スクリプトメッセージ |
| script.lua | `locale/ja-jp/script.lua` | 言語ファイル | 日本語スクリプトメッセージ |
| script.lua | `locale/zh-cn/script.lua` | 言語ファイル | 中国語（簡体字）スクリプトメッセージ |
| script.lua | `locale/zh-tw/script.lua` | 言語ファイル | 中国語（繁体字）スクリプトメッセージ |
| script.lua | `locale/pt-br/script.lua` | 言語ファイル | ポルトガル語スクリプトメッセージ |
| script.lua | `locale/es-419/script.lua` | 言語ファイル | スペイン語スクリプトメッセージ |
| meta.lua | `locale/*/meta.lua` | 言語ファイル | 標準ライブラリのメタ情報 |
| setting.lua | `locale/*/setting.lua` | 言語ファイル | 設定項目の説明 |
