# 通知設計書 7-Language switched

## 概要

本ドキュメントは、OpenCodeアプリケーションにおける「Language switched（言語切り替え）」トースト通知の設計を記述します。アプリケーションの表示言語が切り替わった際に、ユーザーに対してアプリ内トースト通知を表示する機能です。

### 本通知の処理概要

**業務上の目的・背景**：OpenCodeは多言語対応しており、英語、日本語、中国語、韓国語など16言語をサポートしています。言語変更はUI全体のテキスト表示に影響するため、変更が適用されたことをユーザーに明確にフィードバックする必要があります。特に、変更後の言語が期待通りか確認できることは重要です。

**通知の送信タイミング**：ユーザーが言語を切り替えた時（setLocale関数またはcycleLanguage関数実行時）に即座に送信されます。コマンドパレットからの言語選択またはキーボードショートカットによるサイクルで発火します。

**通知の受信者**：言語を切り替えたユーザー本人。設定による制御はなく、常に表示されます。

**通知内容の概要**：通知タイトル「Language」と、「Switched to {言語名}」という説明が表示されます。言語名は切り替え先の言語のネイティブ表記（例：日本語、한국어）で表示されます。

**期待されるアクション**：ユーザーは通知で新しい言語名を確認し、意図した言語に切り替わったことを認識します。意図しない言語の場合は再度言語を切り替えることが想定されます。

## 通知種別

アプリ内トースト通知（一時的）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ユーザーアクション直後） |
| 優先度 | 低 |
| リトライ | なし |

### 送信先決定ロジック

1. ユーザーが言語切り替えアクションを実行
2. 現在の言語と同じ場合は何もしない
3. language.setLocale()で言語を変更
4. 変更完了後、showToast()でトースト表示

## 通知テンプレート

### アプリ内トースト通知の場合

| 項目 | 内容 |
|-----|------|
| タイトル | `toast.language.title`（"Language"） |
| 説明 | `toast.language.description`（"Switched to {{language}}"） |
| 永続性 | なし（自動消去） |
| アクション | なし |

### 本文テンプレート

```
タイトル: Language
説明: Switched to {languageName}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルは使用されません |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| language | 言語の表示名 | language.label(locale) | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ユーザーアクション | コマンドパレットから言語選択 | 現在の言語と異なる場合 | 言語設定時 |
| ユーザーアクション | language.cycleコマンド | 常に | 言語サイクル実行時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 現在の言語と同じ選択 | setLocale関数内でスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[言語切り替えアクション] --> B{現在の言語と同じ?}
    B -->|Yes| C[何もしない]
    B -->|No| D[language.setLocale実行]
    D --> E[言語名取得]
    E --> F[showToast呼び出し]
    F --> G[トースト表示]
    G --> H[自動消去]
    C --> I[終了]
    H --> I
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| LOCALES | 利用可能言語一覧 | LanguageContextで定義 |

### テーブル別参照項目詳細

#### LOCALES

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| locale | 言語コード | "en" / "ja" / "zh" など |
| label | 言語表示名 | language.label(locale) |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 通知自体は状態更新を行わない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 無効なロケール | LOCALESに含まれないロケール | "en"にフォールバック |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（24時間配信可能）

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

- 言語名はシステム定義のため、セキュリティリスクは低い
- ユーザー入力を含まない

## 備考

- サポート言語は16言語（en, zh, zht, ko, de, es, fr, da, ja, pl, ru, ar, no, br, th, bs）
- 言語設定はCookieとローカルストレージの両方に保存
- document.documentElement.langも自動更新される
- cycleLanguage関数はキーボードショートカット未割当（コマンドパレットのみ）

---

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

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

### 推奨読解順序

#### Step 1: 言語定義を理解する

サポート言語の定義を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | language.tsx | `packages/app/src/context/language.tsx` | LOCALES配列（64-81行目）でサポート言語を理解 |
| 1-2 | language.tsx | `packages/app/src/context/language.tsx` | LABEL_KEY（83-100行目）で言語ラベルキーを理解 |

**読解のコツ**: Locale型は16言語のunion型として定義されている。

#### Step 2: トリガー処理を理解する

言語切り替え関数を理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | layout.tsx | `packages/app/src/pages/layout.tsx` | setLocale関数（263-270行目）で言語設定ロジックを理解 |
| 2-2 | layout.tsx | `packages/app/src/pages/layout.tsx` | cycleLanguage関数（272-279行目）でサイクルロジックを理解 |

**主要処理フロー**:
1. **264行目**: 現在の言語と同じ場合は早期リターン
2. **265行目**: language.setLocale()で言語設定
3. **266-269行目**: showToast()でトースト表示

#### Step 3: コマンド登録を理解する

言語関連コマンドの登録を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | layout.tsx | `packages/app/src/pages/layout.tsx` | language.cycle（1046-1050行目）を確認 |
| 3-2 | layout.tsx | `packages/app/src/pages/layout.tsx` | language.set.{locale}（1052-1059行目）を確認 |

**主要処理フロー**:
- **1049行目**: cycleLanguage(1)を呼び出し
- **1058行目**: setLocale(locale)を呼び出し

#### Step 4: i18nキーを理解する

通知テキストの定義を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | en.ts | `packages/app/src/i18n/en.ts` | toast.language.title/description（394-395行目）を確認 |

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

```
コマンドパレット選択
    │
    └─ language.set.{locale} コマンド (layout.tsx:1052-1059)
           │
           └─ setLocale (layout.tsx:263)
                  │
                  ├─ 現在言語チェック
                  │
                  ├─ language.setLocale(next) - 言語設定
                  │
                  └─ showToast (toast.tsx:118)
                         ├─ title: "Language"
                         └─ description: "Switched to {label}"

language.cycleコマンド
    │
    └─ cycleLanguage (layout.tsx:272)
           │
           ├─ インデックス計算
           │
           └─ setLocale(next) - 上記と同じ
```

### データフロー図

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

ユーザーアクション          Layout - setLocale
言語選択         ────▶    現在言語チェック  ───────────────▶   トースト通知
                          language.setLocale()               UI更新
                               │                             Cookie更新
                               ▼
                          showToast({
                            title: "Language",
                            description: "Switched to {label}"
                          })
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| layout.tsx | `packages/app/src/pages/layout.tsx` | ソース | setLocale/cycleLanguage関数 |
| language.tsx | `packages/app/src/context/language.tsx` | ソース | LanguageContext・言語状態管理 |
| toast.tsx | `packages/ui/src/components/toast.tsx` | ソース | showToast関数 |
| en.ts | `packages/app/src/i18n/en.ts` | 設定 | 翻訳キー定義 |
| ja.ts | `packages/app/src/i18n/ja.ts` | 設定 | 日本語翻訳 |
