開発プロジェクトでスペルチェック用辞書を共有する方法

# はじめに
　IntelliJ IDEA 及び Android Studio の提供するスペルチェック機能用の辞書を、開発プロジェクト内で共有する方法を説明します。
![sample05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219474/1cf6ef82-dd5a-e5ec-a869-a82b1d89f308.png)

## ◆ 概要
- IDEからデフォルトで提供されるスペルチェック機能を利用します。
- Project-level dictionary と呼ばれる辞書を利用して、プロジェクトレベルで辞書を共有します。
- 辞書は通常のプロジェクトファイルと同様に VCS で共有します。

## ◆ Project-level dictionary とは
- プロジェクトレベルで共有可能な辞書。
- 辞書ファイルは idea/dictionaries フォルダ以下に格納される。

# 標準の辞書ファイル方式
　標準の辞書ファイル方式には以下のような特徴があります。

- 辞書ファイルが存在しない場合は、単語を登録する際に自動で生成される。
- 辞書ファイルは idea/dictionaries/_username_.xml に格納される。[^5]
- OS のログインユーザー名毎に別ファイルになるので VCS 上でコンフリクトしにくい。

## ◆ 導入手順
0. `Ctrl+Alt+S` / `⌘,` で **Settings** ダイアログを表示し、**Editor** 内の **Spelling** を選択する。
0. **Dictionaries** タブ内の **Advanced settings** から **Use single dictionary for saving words** をチェックし、**project-level** を選択する。[^2]
0. **OK** ボタンを押下する。

![set_using_project_leve_dictionary.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219474/ddfecaa5-a528-8f08-5021-db092da5a2e2.png)

## ◆ 利用方法

### ☆ 単語の登録

#### 警告個所からの登録
0. 警告個所で `ALT+Enter` / `⌥⏎` を入力する。 
0. **Save '**_typo文字列_**' to project-level dictionary** を選択する。

`↓` Typoの個所が波線で表示されている
![sample01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219474/ce0444b3-2e80-b9a3-4719-5517927d5259.png)

`↓` `ALT+Enter` / `⌥⏎` 押下後
![sample02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219474/fada18c5-140c-ad9e-6929-d6eeb2982440.png)

#### Settingsからの登録
0. `Ctrl+Alt+S` / `⌘,` で **Settings** ダイアログを表示し、**Editor** 内の **Spelling** を選択する。
0. **Accepted Words** タブ内の **+** ボタンを押下する。(`Alt+Insert` / `⌘N`)
0. **Add New Word** ダイアログに単語を入力して **OK** ボタンを押下する。
0. **Settings** ダイアログの **OK** ボタンを押下する。

![sample03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219474/2c07e384-2ada-1d4b-782b-ef42efdcbeb4.png)

### ☆ 単語の削除
0. `Ctrl+Alt+S` / `⌘,` で **Settings** ダイアログを表示し、**Editor** 以下の **Spelling** を選択する。
0. **Accepted Words** タブ内で削除対象の単語を選択し、**-** ボタンを押下する。(`Alt+Delete` / `⌘⌦`)
0. **OK** ボタンを押下する。

![sample04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219474/a3187726-98eb-313a-706a-d1e4aa378510.png)

### ☆ Gitリポジトリでの共有
　`.idea/dictionaries/` 以下を `.gitignore` に含めないようにして共有します。

# 任意追加の辞書ファイル方式

　Project-level dictionary の辞書ファイルは、デフォルトでは idea/dictionaries/_username_.xml という形で、_username_ の部分が OS のユーザー名のファイル名になります。しかし、同様のフォーマットであれば、idea/dictionaries 以下に配置されたファイルはすべて辞書ファイルとして認識されます。そこで、プロジェクト内でカブらない名前の辞書ファイル名にすればユーザー名に依存しない custom dictionary として利用できます。

任意追加の辞書ファイル方式には以下のような特徴があります。

- 辞書ファイルは自動生成されない。(つまりIDEから想定されている使い方ではないということ)
- IDEの機能を使って単語の登録や編集ができない。(つまりIDEから想定されている使い方ではないということ)
- `↑` のため、辞書ファイルが変更されるたびに IDE の再起動が必要になる。
- 辞書ファイルは idea/dictionaries/_xxx_.xml に格納される。[^6]
- 辞書ファイルが複数の開発者で共有されるのでコンフリクトしやすい。
- 辞書ファイルに OS のユーザー名が利用されないという点でなんとなく気分がよい。

## ◆ 推奨・非推奨
- プロジェクトレベルの辞書で、変更されない、もしくは変更頻度が小さい場合は推奨。[^8]
- 各ユーザーが適宜辞書を変更する場合は非推奨。[^7]

※個人的な意見ですのでご参考まで...

## ◆ 導入手順

0. 辞書ファイル名を考える。
0. idea/dictionaries 以下に辞書ファイルを作成する。
0. IDEを再起動する

以下、idea/dictionaries/project_dic.xml として辞書ファイルを配置する例：

**空の辞書ファイルの場合**

```xml
<component name="ProjectDictionaryState">
  <dictionary name="project_dic" />
</component>
```

**2単語を含んだ辞書ファイルの場合**

```xml
<component name="ProjectDictionaryState">
  <dictionary name="project_dic">
    <words>
      <w>piroshki</w>
      <w>matrioshka</w>
    </words>
  </dictionary>
</component>
```

## ◆ 利用方法

### ☆ 単語の編集

0. 辞書ファイルを編集する。
0. IDEを再起動する。

### ☆ Gitリポジトリでの共有
- 辞書ファイルを `.gitignore` に含めないようにして共有します。

# トラブルシューティング
## ◆ 辞書の内容が反映されない場合
- IDEを再起動する。

※辞書周りをいろいろいじってる時には結構よく起こります、、、(´・ω・`)

## ◆ 他のメンバーの辞書の内容が反映されない場合
- .gitignore で .idea/dictionaries 以下を除外している場合は除外をやめて辞書データを同期します。
- IDEを再起動する。

# メモ
- Project-level dictionary のデータファイルが username 毎に分かれているのは、おそらく vcs 上の conflict を可能な限り避けるための仕様であり、User-specific であることを意図したものではないと思われます。(名称が Project-level dictionary ということからも自明)。
- [gitignore.io](https://www.gitignore.io/) で AndroidStudio を選択して .gitignore を作成すると .idea/dictionaries が `# User-specific configurations` として除外されてしまうのですが、Project-level dictionary なので User-specific として除外するのは間違いのような気がします。
- Hunspell 辞書の利用も可能。

[^1]: IntelliJ IDEA でもOK.
[^2]: **application-level** を選択した場合、辞書がアプリケーション内部に閉じてしまい、プロジェクトレベルでの共有ができなくなる。(Win環境だと `%HOMEPATH%\.AndroidStudio3.5\config\options\cachedDictionary.xml` のような位置に配置される)
[^3]: その１はこちら。
[^5]: `username` は os のログインユーザー名。
[^6]: `xxx` は os のログインユーザー名とカブらない任意の文字列。
[^7]: この方式はIDEが想定する方式ではないため、動作がバギーだし、IDE側の実装変更により想定外の動作を引き起こす可能性がある。また、この方式を望むのはおそらくユーザー名が利用されていて気持ち悪いという理由であると思うが、単純にコンフリクト対策の仕様(とおいらは思っている)であり、ユーザー名は単なるハッシュのような衝突しにくい記号として利用されているだけであり、意味的にユーザー名として利用されているわけではないので、設計的には何ら問題はないはず(とおいらは思っている)。
[^8]: この方式はIDEが想定する方式ではないが、他方式よりも現在(2019/12/20現在)のところはメリットが多い。正規の方法として独自の custom dictionary を追加するという方法もありますが、VCS にて辞書ファイルを共有しても、**辞書ファイルのパスが workspace.xml に格納される**ため、**プロジェクト管理の辞書としては向かない**と思われます。