# 機能設計書 13-言語切替検索

## 概要

本ドキュメントは、Wikipedia iOSアプリにおける「言語切替検索」機能の設計を記述する。この機能は、検索時にユーザーが検索対象の言語を切り替えることを可能にするものである。

### 本機能の処理概要

**業務上の目的・背景**：Wikipediaは300以上の言語版が存在し、ユーザーは複数言語の記事を参照する可能性がある。言語切替検索機能により、ユーザーは検索バーの近くに表示される言語バーから素早く検索言語を切り替えることができる。これにより、多言語ユーザーの利便性が大幅に向上する。

**機能の利用シーン**：Search画面で検索を行う際、画面上部に言語バーが表示される。ユーザーは優先言語リストから言語を選択するか、「More」ボタンから全言語リストにアクセスして言語を選択できる。言語を選択すると、その言語のWikipediaに対して検索が実行される。

**主要な処理内容**：
1. ユーザーの優先言語リストを言語バーに表示する
2. 言語ボタンのタップで検索言語を切り替える
3. 選択中の言語をUserDefaultsに保存する
4. 言語変更時に検索を再実行する
5. 「More」ボタンから言語追加画面を表示する

**関連システム・外部連携**：MWKLanguageLinkControllerと連携し、ユーザーの優先言語リストを管理する。言語情報はWikipedia APIから取得される。

**権限による制御**：本機能は認証不要で利用可能。すべてのユーザーが言語切替機能を使用できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 4 | Search画面 | 主画面 | 検索時の言語バー表示と言語切り替え |

## 機能種別

UI切替 / 設定管理 / データ取得

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| contentLanguageCode | String | Yes | 選択された言語のコンテンツ言語コード | 有効な言語コードであること |

### 入力データソース

- ユーザー操作：言語バーのボタンタップ
- ユーザー設定：MWKLanguageLinkControllerの優先言語リスト
- UserDefaults：wmf_currentSearchContentLanguageCode

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| selectedSiteURL | URL? | 選択された言語のWikipediaサイトURL |
| selectedSearchContentLanguageCode | String | 選択中の検索言語コード |

### 出力先

- UserDefaults：選択言語の保存
- SearchViewController：言語変更デリゲート通知

## 処理フロー

### 処理シーケンス

```
1. SearchViewControllerが言語バーを表示
   └─ updateLanguageBarVisibility()でSearchLanguagesBarViewControllerを追加
2. 言語バーに優先言語リストを表示
   └─ languageBarLanguages()でMWKLanguageLinkControllerから取得
3. ユーザーが言語ボタンをタップ
   └─ setCurrentlySelectedLanguageToButtonLanguage(withSender:)が呼ばれる
4. 選択言語をUserDefaultsに保存
   └─ wmf_setCurrentSearchContentLanguageCode()
5. デリゲートに言語変更を通知
   └─ searchLanguagesBarViewController(_:didChangeSelectedSearchContentLanguageCode:)
6. SearchViewControllerが検索を再実行
   └─ search()を呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[言語バー表示] --> B[優先言語ボタン描画]
    B --> C{ユーザー操作}
    C -->|言語ボタンタップ| D[選択言語を設定]
    C -->|Moreボタンタップ| E[言語選択画面表示]
    D --> F[UserDefaults保存]
    F --> G[デリゲート通知]
    G --> H[検索再実行]
    E --> I[言語選択]
    I --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-13-01 | 言語バー表示 | UserDefaults.wmf_showSearchLanguageBar()がtrueの場合のみ表示 | 言語バー表示時 |
| BR-13-02 | 言語コード表示 | 言語コードは最大4文字に切り詰め、末尾の句読点を除去 | 言語ボタン表示時 |
| BR-13-03 | デフォルト言語 | 選択言語がない場合はアプリ言語を使用 | 初回起動時 |
| BR-13-04 | 言語追加 | 選択した言語が優先言語リストにない場合、インデックス2に追加 | More画面からの言語選択時 |
| BR-13-05 | ツールチップ | 優先言語が2つ以上あり、初回表示時にMoreボタンツールチップを表示 | showMoreLanguagesTooltipIfNecessary |

### 計算ロジック

言語コードの切り詰め処理:
```swift
// 言語コードを最大4文字に切り詰め、末尾の句読点を除去
languageCode?.localizedUppercase.prefix(4)
    → 末尾が句読点なら除去
```

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

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

| 操作 | 対象 | 操作種別 | 概要 |
|-----|------|---------|------|
| 言語取得 | UserDefaults | SELECT | wmf_currentSearchContentLanguageCode |
| 言語保存 | UserDefaults | UPDATE | wmf_setCurrentSearchContentLanguageCode |
| ツールチップ表示状態 | UserDefaults | SELECT/UPDATE | wmf_didShowMoreLanguagesTooltip |

### テーブル別操作詳細

#### UserDefaults

| 操作 | 項目（キー） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT/UPDATE | currentSearchContentLanguageCode | 選択中の言語コード | - |
| SELECT/UPDATE | didShowMoreLanguagesTooltip | ツールチップ表示済みフラグ | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーションエラー | appLanguageが未設定 | assertionFailureで警告 |

### リトライ仕様

特になし。

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

UserDefaultsへの保存は単一操作で完結。

## パフォーマンス要件

- 言語切替から検索再実行まで即座に実行
- 言語バーの描画はviewWillAppearで完了

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

- 言語設定はローカルデバイスにのみ保存
- 特別な認証は不要

## 備考

SearchFunnel.shared.logSearchLangSwitch()で言語切替イベントのログ記録が行われる。

---

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

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

### 推奨読解順序

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

言語情報のデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MWKLanguageLink | `WMF Framework/` | 言語情報を表すクラス、languageCode/contentLanguageCode/siteURLなど |

**読解のコツ**: languageCodeは言語識別子（例：en, ja）、contentLanguageCodeは言語バリアント対応（例：zh-hans, zh-hant）。siteURLでWikipediaサイトを特定。

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

SearchLanguagesBarViewControllerが言語バーのメインコントローラー。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SearchLanguagesBarViewController.swift | `Wikipedia/Code/SearchLanguagesBarViewController.swift` | 言語バーの管理ViewController |

**主要処理フロー**:
1. **136-156行目**: selectedSearchContentLanguageCode - 選択言語の取得/設定、UserDefaultsとの連携
2. **158-161行目**: selectedSiteURL - 選択言語のサイトURL取得
3. **234-236行目**: languageBarLanguages() - 優先言語リストの取得
4. **242-264行目**: updateSearchLanguageButtons() - 言語ボタンの更新処理
5. **290-297行目**: setCurrentlySelectedLanguageToButtonLanguage - ボタンタップ時の処理
6. **299-307行目**: openLanguagePicker - More画面の表示

#### Step 3: カスタムボタンを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SearchLanguageButton | `Wikipedia/Code/SearchLanguagesBarViewController.swift` (8-108行目) | カスタム言語ボタンクラス |

**主要処理フロー**:
- **12-22行目**: languageCodeプロパティ - 言語コードの設定と切り詰め処理
- **49-96行目**: setup() - ボタンのレイアウト設定
- **100-106行目**: apply(theme:) - テーマ適用

#### Step 4: SearchViewControllerとの連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SearchViewController.swift | `Wikipedia/Code/SearchViewController.swift` | 検索画面のメインViewController |

**主要処理フロー**:
- **266-308行目**: updateLanguageBarVisibility() - 言語バーの表示/非表示切替
- **663-668行目**: SearchLanguagesBarViewControllerDelegate実装 - 言語変更時の検索再実行

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

```
SearchViewController
    │
    ├─ SearchLanguagesBarViewController
    │      ├─ SearchLanguageButton (複数)
    │      ├─ UIScrollView (横スクロール)
    │      └─ otherLanguagesButton (More)
    │
    ├─ MWKLanguageLinkController
    │      └─ preferredLanguages取得
    │
    └─ UserDefaults
           └─ 選択言語の永続化
```

### データフロー図

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

言語ボタンタップ ───▶ SearchLanguagesBarViewController ───▶ 検索再実行
                           │
                           ├─▶ UserDefaults保存
                           │
                           └─▶ SearchViewControllerDelegate
                                   └─▶ search()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SearchLanguagesBarViewController.swift | `Wikipedia/Code/` | ソース | 言語バー管理ViewController |
| SearchViewController.swift | `Wikipedia/Code/` | ソース | 検索画面ViewController |
| MWKLanguageLinkController | `WMF Framework/` | ソース | 言語情報管理 |
| MWKLanguageLink | `WMF Framework/` | ソース | 言語データモデル |
| WMFPreferredLanguagesViewController | `WMF Framework/` | ソース | 言語選択画面 |
| SearchLanguagesBarViewController.xib | `Wikipedia/` | XIB | 言語バーのレイアウト |
