# 帳票設計書 6-翻訳テンプレートCSV

## 概要

本ドキュメントは、プロジェクト内の翻訳可能な文字列を抽出し、CSV形式で出力する帳票の設計書である。

### 本帳票の処理概要

本帳票は、Godotプロジェクト内のスクリプトやシーンファイルから翻訳対象となる文字列を抽出し、CSV形式のテンプレートファイルとして出力する機能を提供する。Excel等の表計算ソフトでの翻訳作業に適した形式であり、Gettextに馴染みのない翻訳者でも扱いやすい形式を提供する。

**業務上の目的・背景**：POT形式はGettext専用ツールが必要だが、CSV形式はExcel、Google Spreadsheet、LibreOffice Calcなど汎用的なツールで編集できる。翻訳者のスキルセットや既存のワークフローに合わせて、より親しみやすい形式で翻訳作業を行えるようにする。

**帳票の利用シーン**：主に以下のシーンで利用される。1) Excelベースの翻訳ワークフロー、2) 翻訳会社への外注時、3) スプレッドシートでの協調翻訳作業、4) 翻訳文字列の一括確認・レビュー。

**主要な出力内容**：
1. キー（翻訳対象文字列）
2. コンテキスト（オプション）
3. 複数形（オプション）
4. 翻訳者向けコメント（オプション）
5. ファイル位置情報（オプション）

**帳票の出力タイミング**：エディタのプロジェクト設定 > ローカライゼーション > POT生成で、出力ファイル名を.csv拡張子で指定した際に出力される。

**帳票の利用者**：ローカライゼーションエンジニア、翻訳コーディネーター、翻訳者

## 帳票種別

テンプレートファイル / 翻訳用データ出力

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | プロジェクト設定 | Project > Project Settings > Localization > POT Generation | 「Generate POT」ボタン（.csv拡張子指定時） |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | CSV |
| 用紙サイズ | N/A（データファイル） |
| 向き | N/A |
| ファイル名 | ユーザー指定（.csvフィルター） |
| 出力方法 | プロジェクト設定からのファイル保存 |
| 文字コード | UTF-8 |

### CSV固有設定

| 項目 | 内容 |
|-----|------|
| 区切り文字 | カンマ（,） |
| 囲み文字 | ダブルクォート（必要時） |
| ヘッダー行 | あり（動的に列を追加） |

## 帳票レイアウト

### レイアウト概要

CSVファイルは使用されているカラムのみが出力される動的構造を持つ。

```
┌─────────────────────────────────────────────────────────────┐
│              ヘッダー行（key, [?context], [?plural], ...）   │
├─────────────────────────────────────────────────────────────┤
│              データ行（翻訳文字列ごとの情報）                  │
│              ...（文字列数分の行）                            │
└─────────────────────────────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | 必須 | 表示形式 |
|----|-------|------|-----|---------|
| 1 | key | 翻訳対象文字列（msgid） | Yes | 固定 |
| 2 | ?context | コンテキスト（msgctxt） | No | context_usedの場合追加 |
| 3 | ?plural | 複数形（msgid_plural） | No | plural_usedの場合追加 |
| 4 | _comments | 翻訳者向けコメント | No | comments_usedの場合追加 |
| 5 | _locations | ファイル位置情報 | No | locations_usedの場合追加 |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | key | 翻訳対象文字列 | MessageKey::msgid | 文字列 | 可変 |
| 2 | ?context | コンテキスト | MessageKey::msgctxt | 文字列 | 可変 |
| 3 | ?plural | 複数形原文 | MessageData::plural | 文字列 | 可変 |
| 4 | _comments | コメント一覧 | MessageData::comments | 改行区切り文字列 | 可変 |
| 5 | _locations | 位置情報一覧 | MessageData::locations | 改行区切り文字列 | 可変 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| 抽出対象ファイル設定 | translations_pot_filesに対象ファイルが設定されている | Yes |
| パーサー対応 | 対象ファイルの拡張子に対応するパーサーが存在する | Yes |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | MessageMap内部順序 | HashMap内部順 |

### 改ページ条件

N/A（CSVファイルのため改ページなし）

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照せず、プロジェクト設定とソースファイルからデータを取得する。

| データソース | 用途 | 取得方法 |
|-----------|------|---------|
| internationalization/locale/translations_pot_files | 抽出対象ファイル一覧 | GLOBAL_GET |
| internationalization/locale/translation_add_builtin_strings_to_pot | 組み込み文字列追加フラグ | GLOBAL_GET |
| EditorTranslationParser | ファイルからの文字列抽出 | get_singleton()->parse_file() |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| context_used | !msgctxt.is_empty()が1つでもtrue | N/A | カラム追加判定 |
| plural_used | !plural.is_empty()が1つでもtrue | N/A | カラム追加判定 |
| comments_used | !comments.is_empty()が1つでもtrue | N/A | カラム追加判定 |
| locations_used | !locations.is_empty()が1つでもtrue | N/A | カラム追加判定 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[_write_to_csv呼び出し] --> B[使用カラム判定ループ]
    B --> C{context使用?}
    C -->|Yes| D[context_used = true]
    C -->|No| E{plural使用?}
    D --> E
    E -->|Yes| F[plural_used = true]
    E -->|No| G{comments使用?}
    F --> G
    G -->|Yes| H[comments_used = true]
    G -->|No| I{locations使用?}
    H --> I
    I -->|Yes| J[locations_used = true]
    I -->|No| K[ヘッダー行構築]
    J --> K
    K --> L[header = key を設定]
    L --> M{context_used?}
    M -->|Yes| N[?context追加]
    M -->|No| O{plural_used?}
    N --> O
    O -->|Yes| P[?plural追加]
    O -->|No| Q{comments_used?}
    P --> Q
    Q -->|Yes| R[_comments追加]
    Q -->|No| S{locations_used?}
    R --> S
    S -->|Yes| T[_locations追加]
    S -->|No| U[store_csv_line header]
    T --> U
    U --> V[データ行ループ]
    V --> W[line構築]
    W --> X[store_csv_line line]
    X --> Y{次のエントリ?}
    Y -->|Yes| V
    Y -->|No| Z[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| 翻訳文字列なし | mapが空 | "No translatable strings found." | 上位関数で警告表示 |
| ファイルオープン失敗 | 書き込み権限なし等 | "Failed to open [path]" | 上位関数でエラー処理 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数百〜数千の翻訳文字列 |
| 目標出力時間 | プロジェクトサイズに依存 |
| 同時出力数上限 | 1（シングル処理） |

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

- プロジェクト内の文字列がすべて出力されるため、機密情報が含まれないか注意
- ファイルパスからプロジェクト構造が推測可能

## 備考

- カラムは使用されている場合のみ出力される（動的カラム）
- ?プレフィックスはGodotのCSV翻訳ファイル規約に従う（オプション列を示す）
- _プレフィックスは翻訳に使用しない補助情報列を示す
- コメントと位置情報は改行で結合される

---

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

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

### 推奨読解順序

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

POT出力と同じMessageMap構造を使用する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | template_generator.h | `editor/translations/template_generator.h` | MessageData、MessageMapの定義 |

#### Step 2: CSV出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | template_generator.cpp | `editor/translations/template_generator.cpp` | _write_to_csv()（229-283行目） |

**主要処理フロー**:
1. **231-250行目**: 使用カラムの判定ループ（context, plural, comments, locations）
2. **252-264行目**: ヘッダー行の構築（使用されるカラムのみ追加）
3. **265行目**: store_csv_line(header)でヘッダー出力
4. **267-281行目**: データ行のループ処理

#### Step 3: 補助関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | template_generator.cpp | `editor/translations/template_generator.cpp` | _join_strings()（216-227行目） |

**処理内容**:
- HashSet<String>を改行区切りの単一Stringに結合

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

```
TranslationTemplateGenerator::_write_to_csv(p_file, p_map)
    │
    ├─ カラム使用判定ループ
    │      │
    │      ├─ !E.key.msgctxt.is_empty() → context_used
    │      │
    │      ├─ !E.value.plural.is_empty() → plural_used
    │      │
    │      ├─ !E.value.comments.is_empty() → comments_used
    │      │
    │      └─ !E.value.locations.is_empty() → locations_used
    │
    ├─ ヘッダー行構築
    │      │
    │      ├─ header = { "key" }
    │      │
    │      ├─ [context_used] → header.push_back("?context")
    │      │
    │      ├─ [plural_used] → header.push_back("?plural")
    │      │
    │      ├─ [comments_used] → header.push_back("_comments")
    │      │
    │      └─ [locations_used] → header.push_back("_locations")
    │
    ├─ p_file->store_csv_line(header)
    │
    └─ データ行ループ
           │
           ├─ line = { E.key.msgid }
           │
           ├─ [context_used] → line.push_back(E.key.msgctxt)
           │
           ├─ [plural_used] → line.push_back(E.value.plural)
           │
           ├─ [comments_used] → line.push_back(_join_strings(E.value.comments))
           │
           ├─ [locations_used] → line.push_back(_join_strings(E.value.locations))
           │
           └─ p_file->store_csv_line(line)
```

### データフロー図

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

MessageMap ──────────────▶ カラム使用判定 ─────────────────▶ フラグ4種
      │                                                    (context_used等)
      │                                                         │
      │                                                         │
      │                   ヘッダー行構築 ◀──────────────────────┘
      │                        │
      │                        ▼
      │                   store_csv_line(header) ──────────▶ CSVヘッダー行
      │                                                         │
      │                                                         │
      └──────────────────▶ データ行構築 ─────────────────────▶ CSVデータ行
                               │
                               │
                          _join_strings()
                               │
                               ▼
                          [CSVファイル]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| template_generator.h | `editor/translations/template_generator.h` | ヘッダー | TranslationTemplateGeneratorクラス定義 |
| template_generator.cpp | `editor/translations/template_generator.cpp` | ソース | _write_to_csv()、_join_strings()実装 |
| file_access.h | `core/io/file_access.h` | ヘッダー | store_csv_line()メソッド定義 |
