Angularでi18nするときはngx-translateがよさそうという話です。
Angularのi18nについて
Angularでは公式の i18n 機能が提供されており、 Angular CLIでも辞書ファイルの生成コマンドを用意していたりと公式でのサポートも手厚い印象です。
(angular i18n
でGoogle検索してもTopには公式のドキュメントがヒットします)
そのため、まずはこれを使ってみることも多いかと思います。
自分も、以前公式のi18n機能を使ってアプリケーションの多言語化を行ったことがありますが、その時以下の点に課題を感じていました。
- 翻訳箇所が増えた際に辞書ファイルを更新する手間がかかる
- Angularのi18nを使用する場合、Angular CLIが提供する
ng i18n
コマンドを使って辞書ファイルの作成が行なえますが更新操作がなく都度作り直す必要があります
- Angularのi18nを使用する場合、Angular CLIが提供する
- htmlタグに直接記述、テンプレートシンタックスを使って表示した変数以外への対応
- 具体的には以下のようなユースケース
- component classから chartライブラリにラベル文字列を入力する
- service classAngular MaterialのSnackbarのようなAPIを呼び出す
- 具体的には以下のようなユースケース
一度使ってみると、Angularで国際化対応 - 闘うITエンジニアの覚え書き で触れられている 2つの方法を比較した所感
の内容に完全に同意できます...
ngx-translate
Angular公式のi18nの次に候補になるのが、 ngx-translate ではないかと思います。
導入/基本的な使い方などは、ドキュメントも充実しているのですんなりセットアップもできました。
個人的に、 「公式でフルスタックな機能を提供していて、Angularチームが作っているものを選んでおけば間違いない」 という印象がありましたが、i18n周りに関してはngx-translateを選択したほうが幸せになれそうな印象があります。
今回は、このライブラリを使った際にググりがちなポイントを何点か紹介していきたいと思います。
いろいろなパターンへの対応
前提として、Angularプロジェクトへの導入が済んでいる状態で、en.json
という次のような辞書ファイルが定義されていることとします。
{
"ログイン": "Member Login / Sign In",
"認証情報を入力してください": "Input Your Accout Information",
"ログインID": "User ID",
"パスワード": "Password",
...
}
最も基本的なパターン
htmlタグに直接記述された文字列を翻訳するパターンでは、次のようにタグに translate
ディレクティブをつけるだけです。
<h2 class="title" translate>ログイン</h2>
<p class="caption" translate>認証情報を入力してください</p>
button
htmlタグのbutton
に対応する場合、次のように単純に translate
ディレクティブをつけるだけでは翻訳されません。
<button class="button" (click)="login()" translate>ログイン</button>
次のようにspanなどのインライン要素で翻訳箇所をラップすることで、buttonなどにも対応することができます。
<button class="button" (click)="login()"><span translate>ログイン</span></button>
placeholderなどのhtml属性
以下は、placeholderの例です。
Interpolationを使って、translate
をpipeとして使うことでplaceholderのhtml属性を翻訳することができます。
<input type="text" matInput placeholder="{{ 'ログインID' | translate }}">
servieやcomponentのmodelの文言
最初の項目に挙げた次のようなユースケースです。
- 具体的には以下のようなユースケース
- component classから chartライブラリにラベル文字列を入力する
- service classAngular MaterialのSnackbarのようなAPIを呼び出す
ngx-translateが提供する TranslateService
の instant()
メソッドを使うことで、serviceやcomponentのmodel側からも翻訳後の文字列を簡単に取得することができます。
import { Injectable } from '@angular/core';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
@Injectable({
providedIn: 'root',
})
export class NotificationService {
constructor(private readonly snackBar: MatSnackBar, private readonly translateService: TranslateService) {}
add(message: string): void {
this.openSnackBar(message);
}
addWithDismiss(message: string): void {
this.openSnackBar(message, this.translateService.instant('閉じる'));
}
private openSnackBar(message: string, action?: string): void {
const option: MatSnackBarConfig = {
horizontalPosition: 'right',
verticalPosition: 'bottom',
};
if (!action) {
option.duration = 2000;
}
const translatedMessage = this.translateService.instant(message);
this.snackBar.open(translatedMessage || message, action, option);
}
}
参考
https://github.com/ngx-translate/core
https://angular.io/guide/i18n
https://www.magata.net/memo/index.php?Angular%A4%C7%B9%F1%BA%DD%B2%BD%C2%D0%B1%FE