VS Code 拡張機能のコマンドタイトル名をローカライズしてみる

VS Code 拡張機能で提供するコマンド・タイトルに英語表記以外の各言語を割り当ててローカライズしてみる。

<img width="623" alt="2016-12-04-14-42-12.png" src="https://qiita-image-store.s3.amazonaws.com/0/65800/718dbce7-4995-0a5b-149d-2f1dd6894ff4.png">

提供するコマンドのタイトル名は、package.json の `contributes` ポイントにある `commands` セクションに定義され、Yeoman の generator-code (yo code) で作成される Hello World サンプルを見てみると下記のようになっています。

* [Example - Hello World](https://code.visualstudio.com/docs/extensions/example-hello-world)

**package.json:** 

```json
    "contributes": {
        "commands": [{
            "command": "extension.sayHello",
            "title": "Hello World"
        }]
    },
```

コマンドパレットから `extension.sayHello` を実行するには、`Hello World` を見つけて選択すれば実行されることがわかりますね。
この `Hello World` がコマンドのタイトル名になります。

## **package.nls.json と package.nls.ja.json**

`Hello World` のままでも良いのですが、このタイトルを日本語にローカライズしてみるのが目的となります。 

拡張機能の `package.json` に定義される `"title"` は、全ての言語で共通に利用されますが、`package.json` と同一のディレクトリに下記のファイルを配置することで言語毎にローカライズされたタイトルなどを追加することが可能になります。

* **package.nls.json**
* **package.nls.ja.json**: (本記事では日本語をターゲットにしているため、ja のみ絞ります)

### **まず、`package.json` の変更:** 

* ローカライズしたい文字列を `%extension.sayHello.title%` のように `%` で囲まれた文字列に置き換えます。これがキーになります
* 本記事では `"category":` を追加し、コマンドパレット上では `category: title` のように表示するようにします。ここでは、`"Hello World sample"` というカテゴリ名を設定しておきます。

> **修正後の package.json:**

```json
    "contributes": {
        "commands": [{
            "command": "extension.sayHello",
            "title": "%extension.sayHello.title%",
            "category": "Hello World sample"
        }]
    },
```

### **続いて、`package.nls.json` を作成:**

`package.json` で設定したローカライズ用のキーにマッピングするための値を、下記のように追加します。
このファイルを用意することで、VS Code の言語が英語(en)に設定されているか、英語以外のローカライズ情報が用意されていない場合にこのファイルに記載されている情報が利用されることになります。

> **package.nls.json:**

```json
{
  "extension.sayHello.title": "Hello World"
}
```

### **最後にローカライズ用の値が格納された `packahe.nls.ja.json` を作成**

最後に用意するのがローカライズされた値を格納したファイル `packahe.nls.ja.json` (ここでは、ja = 日本語をターゲットにしてます)を作成します。

`"extension.sayHello.title":` に、`"こんにちは！"` を指定することで、`package.json` に定義した `"%extension.sayHello.title%"` が置きかわるという仕組みです。

> **packahe.nls.ja.json:**

```json
{
  "extension.sayHello.title": "こんにちは！"
}
```

表示例です。
コマンドパレットに `Hello World sample: こんにちは！` と表示されています。。
更に、コンテキストメニューにも出してみました。

<img width="1304" alt="2016-12-04-14-43-39.png" src="https://qiita-image-store.s3.amazonaws.com/0/65800/1bd2994d-77f9-75e4-6a11-c5053ecbfb19.png">


## **`"*.category"` をローカライズしてしまうと・・・**

VS Code の built-in Markdown 機能で、コマンドパレットに markdon と入力しても markdown 関連のコマンドがヒットしないのなぜかなーっと思って調べてみると、`"markdown.category": "マークダウン"` と設定されていました。

<img width="613" alt="スクリーンショット 2016-11-26 17.18.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/65800/95af4613-4c34-c45b-020f-ecd06f5351b4.png">

https://github.com/Microsoft/vscode/blob/master/i18n/jpn/extensions/markdown/package.i18n.json#L6-L10

```json
{
	"markdown.category": "マークダウン",
	"markdown.preview.title": "プレビューを開く",
	"markdown.previewSide.title": "プレビューを横に表示",
	"markdown.showSource.title": "ソースの表示"
}
```

* [The category of the markdown command `markdown.category` should not be translated #16087](https://github.com/Microsoft/vscode/issues/16087)

これだと、言語に ja が設定されている環境では、`マークダウン` と入力しないと候補が出てこないことになります。

このように `"category"` プロパティを追加し、そのコマンドが属するカテゴリを指定することができます。
こちらも `%extension.sayHello.category%` の様に `%` で囲まれた文字列とし、ローカライズ用のファイルで定義することも可能であることがわかりますが、`"title"` 共々、ローカライズされた値を設定してしまうと、コマンドパレットからはローカライズされた値でなければ検索対象としてヒットしなくなるため、ローカライズする時は気をつけたいところです。

ちなみに、この Issue #16087 は VS Code 1.8.0-insider 2bd85b8 で修正済みとなりました。

## **設定の概要もローカライズしてみる**

settings.json では、拡張機能毎に様々プロパティが提供され、分かり易くするためにプロパティに概要をつけられるていることが多いです。
この概要のローカライズも、似たような作業で簡単に行うことができます。

[contributes.configuration](https://code.visualstudio.com/docs/extensionAPI/extension-points#_contributesconfiguration) を参考に、settings.json へ設定項目を追加してみます。
項目だけとなりますので、気軽に試してみてください。

> **package.json に追加:**

まずは、肝心のプロパティを追加します。
ここでは、`sayHello` というプロパティをでっちあげます。
そして、`"description"` には、やはり `%` で括った文字列 `"%extension.sayHello.setting.desc%"` を指定します。

```json
    "configuration": {
        "type": "object",
        "title": "Hello World sample",
        "properties": {
            "sayHello": {
                "type": ["string", "null"],
                "default": null,
                "description": "%extension.sayHello.setting.desc%"
            }
        }
    }
```

> **package.nls.json に追加:**

ja 以外では、概要に `"Hello World setting"` と表示するようにします。

```json
  "extension.sayHello.setting.desc": "Hello World setting"
```

> **packahe.nls.ja.json に追加:**

ja では、概要に `"こんにちは！ の設定項目です"` と表示するようにします。

```json
  "extension.sayHello.setting.desc": "こんにちは！ の設定項目です"
```

実行結果は、

"locale: "en" の場合
<img width="1376" alt="スクリーンショット 2016-12-04 23.31.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/65800/4f399270-65d5-0a45-35dd-1a4751f0f42e.png">

"locale: "ja" の場合
<img width="1325" alt="2016-12-04-15-02-33.png" src="https://qiita-image-store.s3.amazonaws.com/0/65800/05b77aae-01dc-3f94-a727-c4b52fa5ed43.png">

とっても簡単です。
ちなみに、この画面は開発中の VS Code Insiders (1.8) のものとなりますが、Default Settings の画面が大きく変更されています。

## **Microsoft/vscode-nls**

この実装は、下記のモジュールで実現されているようです。

* [Microsoft/vscode-nls](https://github.com/Microsoft/vscode-nls)

用意できる言語は、[Display Language](https://code.visualstudio.com/docs/customization/locales) で確認でき、ファイル名は下記を準備し、その言語でメッセージを用意することになります。

* package.json
* package.nls.json
* package.nls.de.json
* package.nls.es.json
* package.nls.fr.json
* package.nls.it.json
* package.nls.ja.json
* package.nls.ko.json
* package.nls.ru.json
* package.nls.zh-cn.json
* package.nls.zh-tw.json

コマンドパレットに英語とローカライズされた値を同時に出力する場合は、vscode-nls を利用し、拡張機能の中でラベルとして扱う必要があるみたい。

## **参考**

* [Contribution Points - package.json](https://code.visualstudio.com/docs/extensionAPI/extension-points)
* [nls support for package.json and common-js #3156](https://github.com/Microsoft/vscode/issues/3156)