VS Code リリースノート - 2022年9月 (version 1.72) から、VS Code 拡張機能のローカライズについて


VS Code の 2022年9月 (version 1.72) 版がリリースされました。
このリリースノートに、VS Code 拡張機能のローカライズに関する記述が含まれているので、その部分を日本語に翻訳したものを以下に掲載しておきます。

簡単に概要をまとめると、これまで VS Code 拡張機能で使用されていた `vscode-nls` と `vscode-nls-dev` の2つを置き換える、新しい API のプロポーザルに関する説明になります。


# API の一部としてのローカライズ

今回のイテレーションでは、拡張機能が文字列をローカライズするための新しい API を導入しています。
これは、過去にローカライズのために使用されていた `vscode-nls` と `vscode-nls-dev` モジュールを置き換えるものです。
これらは引き続き動作しますが、それ以上の機能は提供されません。
新しい API とツールは、使い慣れたものでありながら、より使いやすく、より柔軟な設計になっています。
さらに、VS Code API の一部として含めることで、デスクトップ用の VS Code と Web 用の VS Code の両方で、拡張機能のローカライズのサポートを提供することができます。

VS Code 拡張機能のローカライズには、以下の 4 つの重要な部分があります。



## 1. 新しい vscode.l10n API

```ts
declare module 'vscode' {
  export namespace l10n {
    /**
     * ローカライズバンドルが存在する場合、そこから取得できる文字列。
     */
    export function t(message: string, ...args: any[]): string;
    /**
     * ローカライズバンドルが存在する場合、そこから取得できる文字列。
     */
    export function t(options: { message: string; args?: any[]; comment: string[] }): string;
    /**
     * 拡張機能用にロードされたローカライズされた文字列のバンドル。
     */
    export const bundle: { [key: string]: string };
    /**
     * 拡張機能用にロードされたローカライズ バンドルの URI。
     */
    export const uri: Uri | undefined;
  }
}
```

[vscode.l10n](https://github.com/microsoft/vscode/issues/158213#issuecomment-1241329160) が提案する API は新しい名前空間で、文字列をローカライズすることを宣言するために使用できる単一の関数 `t` を提供します。
この関数は、文字列または `message` プロパティを持つオブジェクトで呼び出すことができます。
この関数は、ローカライズされた文字列が存在する場合はそれを返し、存在しない場合は元の文字列を返します。
この関数は、文字列をフォーマットするために使用できる引数や、翻訳者にコンテキストを提供するために使用できるコメントもサポートしています。

以下のコードは、新しい　API の簡単な使用例です。

```ts
import { l10n } from 'vscode';

export function activate(context: vscode.ExtensionContext) {
  const message = l10n.t('Hello in {0}!', vscode.env.language);
  vscode.window.showInformationMessage(message);
}
```

この例では、現在の言語のローカライズ バンドルが存在する場合、文字列 `Hello in {0}!` がローカライズされます。
`{0}` は現在の言語 (デフォルトでは `en` 、フランス語では `fr`、ブラジルのポルトガル語では `pt-br` など) に置き換えられます。
ローカライズ バンドルが存在しない場合、文字列はそのまま返され、引数でフォーマットされます。
これらのローカリゼーション バンドルがどこから来たのか疑問に思われるかもしれません。
それについては、次のセクションで説明します。

また、`vscode.l10n` API は、ローカライズされた文字列のバンドルや、文字列のバンドルへの URI へのアクセスも提供します。
これは、後で説明するサブプロセスのシナリオで使用することを想定しています。

> **重要**: この API を使用する場合、ローカライズ バンドルの場所を明示的に宣言する必要もあります。 これは、以下のように、`package.json` に `l10n` プロパティを追加することによって行われます。

```json
{
  "main": "./out/extension.js",
  "l10n": "./l10n"
}
```

`l10n` プロパティは、ローカライズ バンドルが格納されているフォルダへの相対パスでなければなりません。



## 2. @vscode/l10n-dev モジュール

[vscode/l10n-dev](https://npmjs.com/package/@vscode/l10n-dev) モジュールは、ローカライズ バンドルを生成するために使用される新しいモジュールです。
コマンドラインツールとして、あるいはライブラリとして使用することができます。 
どちらも、提供されたソースコードから `vscode.l10n.t(...)` の呼び出しをスキャンして、ローカライズバンドルを生成するために使用されます。

コマンドラインツールを使用した簡単な例を次に示します。

```bash
npx @vscode/l10n-dev ./src --out ./l10n
```

これは `./l10n` フォルダーに `bundle.l10n.json` ファイルを配置します。 
そこから、サポートしたいロケールごとに `bundle.l10n.LOCALE.json` ファイルを作成することができます。 
たとえば、上記のコマンドで以下のような `bundle.l10n.json` ファイルが生成されたとします。

```json
{
  "Hello": "Hello",
  "Hello {0}": "Hello {0}",
  "Hello {0}/This is a comment": {
    "message": "Hello {0}",
    "comment": ["This is a comment"]
  }
}
```

フランス語をサポートしたい場合は、以下のような `bundle.l10n.fr.json` ファイルを作成します。

```json
{
  "Hello": "Bonjour",
  "Hello {0}": "Bonjour {0}",
  "Hello {0}/This is a comment": "Bonjour {0}"
}
```

> **注意**: コメントは元のバンドルを翻訳する翻訳者にのみ役立つため、ローカライズされたバンドルにコメントは必要ありません。

`vscode/l10n-dev` モジュールは、 XLF ファイルを生成するために使用することもできます。 
VS Code チームは、作成した XLF ファイルを Microsoft の翻訳者に渡します。 
翻訳者は、翻訳された XLF ファイルを返します。
次に、`@vscode/l10n-dev` モジュールを使用して、翻訳された XLF ファイルからローカライズされたバンドルを生成します。 
ローカライズのプロセス全体については、今後、ブログで詳しく紹介する予定です。



## 3. @vscode/l10n モジュール

`vscode.l10n` API は拡張ホストでのみ使用できるため、サブプロセスでは使用できません。 
このため、ローカライズ バンドルをロードするサブプロセスで使用できる新しいモジュールを作成しました。
そのモジュールは [@vscode/l10n](https://www.npmjs.com/package/@vscode/l10n) と呼ばれ、以下のように使用できます。

```json
import { l10n } from '@vscode/l10n';

// 現在のロケールの翻訳をロードします
l10n.config({
    uri: process.env.BUNDLE_URI_FROM_EXTENSION
});

// 翻訳された文字列、または翻訳が利用できない場合は元の文字列を返します
l10n.t('Hello World');
```

このアイデアは、サブプロセスを起動する拡張側のコードが、 `vscode.l10n.contents` または `vscode.l10n.uri` API を使用して、バンドルまたはその URI をサブプロセスに渡すというものです。 
サブプロセスは、`@vscode/l10n` モジュールを使用してバンドルをロードし、`t` 関数を使用して文字列を変換できます。 
`vscode/l10n` モジュールが使用する `t` 関数は、 `@vscode/l10n-dev` モジュールでも使用されるので、1つのプロセスで文字列の抽出とローカライズができるようになります。



## 4. package.nls.json ファイル

`package.nls.json` ファイルに関しては何も変更されていません。 
これは、ローカライズされるべきデフォルトの文字列を宣言するためにまだ使用されており、 `package.json` の隣にあるはずです。 
この場合でも `package.nls.LOCALE.json` (LOCALE は `de` や `zh-cn` のようなもの) を用意して、ユーザーが VS Code をそのロケールに設定していれば、そのファイルで宣言されている文字列が最初にピックアップされるようにします。 小さな例を以下に示します。

`package.json`:

```json
{
  "name": "my-extension",
  "version": "0.0.1",
  "main": "./out/extension.js",
  "l10n": "./l10n",
  //...
  "contributes": {
    "commands": [
      {
        "command": "my-extension.helloWorld",
        // キーは % 文字で囲まれています
        "title": "%my-extension.helloWorld.title%"
      }
    ]
  }
}
```

`package.nls.json`:

```json
{
  // package.json にある同じキー
  "my-extension.helloWorld.title": "Hello World"
}
```

`package.nls.de.json`:

```json
{
  // package.json にある同じキー
  "my-extension.helloWorld.title": "Hallo Welt"
}
```



## まとめ

ここには説明しなければならないことがたくさんありますが、VS Code 拡張機能のローカライズで私たちが取っている方向性についてのアイデアを得ることができれば幸いです。

完全な例に興味がある場合は、[l10n-sample](https://github.com/microsoft/vscode-extension-samples/tree/tyler/add-l10n-extension-sample/l10n-sample) を確認してください。

ご質問やご意見は、以下の場所でお聞かせください。

- [vscode.l10n の API 提案](https://github.com/microsoft/vscode/issues/158213#issuecomment-1241329160)
- [vscode-l10n](https://github.com/microsoft/vscode-l10n) リポジトリ (`@vscode/l10n-dev` および `@vscode/l10n` モジュールのホーム)