4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Angular】ngx-translateを使った多言語化で、複数の多言語ファイルを利用したい

Posted at

はじめに

タイトルのユースケース例としては、複数のAngularアプリが存在しそれらには固有のアプリIDが振られておりそれぞれのアプリで文言のカスタマイズができるというケース。そこで、

  • どのアプリにも共通して利用される文言
  • アプリごとに設定された文言

この2種類の多言語化を必要としたとき「ngx-translate」を使っている場合は複数の多言語ファイルで管理したくなる。そのときどうしたら実現できるかを共有していく。

まずはインストール

$ npm install --save @ngx-translate/core @ngx-translate/http-loader

app.module.tsに設定を追加

useFactoryの部分が無いが、ここはのちに追加する。

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
+ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { HttpClient } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';

@NgModule({
    declarations: [AppComponent],
    imports: [
        BrowserModule,
        AppRoutingModule,
        CoreModule,
        CoreModule,
+       TranslateModule.forRoot({
+           loader: {
+               provide: TranslateLoader,
+               useFactory: ,
+               deps: [HttpClient],
+           },
+           isolate: false,
+       }),
    ],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

複数の多言語ファイルをロードするため、独自のLoaderを実装

multi-translate-http-loader.ts
import { TranslateLoader } from '@ngx-translate/core';
import { HttpClient } from '@angular/common/http';
import { forkJoin, Observable } from 'rxjs';
import { map } from 'rxjs/operators';

/**
 * 複数の多言語ファイルを読み込むためのカスタムTranslateHttpLoader
 */
class MultiTranslateHttpLoader implements TranslateLoader {
    constructor(
        private http: HttpClient,
        public resources: { prefix: string; suffix: string }[] = [
            {
                prefix: '/assets/language/',
                suffix: '.json',
            },
        ]
    ) {}

    public getTranslation(lang: string): Observable<object> {
        return forkJoin(
            this.resources.map(({ prefix, suffix }) => {
                return this.http.get(`${prefix}${lang}${suffix}`);
            })
        ).pipe(
            map(response => {
                return response.reduce((a, b) => {
                    return Object.assign(a, b);
                });
            })
        );
    }
}

export function createTranslateLoader(http: HttpClient) {
    // TODO: ここでアプリIDをSessionStorageから取得する想定
    const appId = 'app-01';
    console.log('Translateのインスタンス生成');
    return new MultiTranslateHttpLoader(http, [
        // 複数アプリで共通の多言語ファイル
        { prefix: '/assets/language/common/', suffix: '.json' },
        // アプリごとの多言語ファイル
        { prefix: `/assets/language/${appId}/`, suffix: '.json' },
    ]);
}

実装したLoaderをuseFactoryに追加

app.component.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { HttpClient } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';
+ import { createTranslateLoader } from './core/translate/multi-translate-http-loader';

@NgModule({
    declarations: [AppComponent],
    imports: [
        BrowserModule,
        AppRoutingModule,
        CoreModule,
        CoreModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
+               useFactory: createTranslateLoader,
                deps: [HttpClient],
            },
            isolate: false,
        }),
    ],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}

app.component.tsで言語の設定を書く

app.component.ts
import { Component } from '@angular/core';
+ import { TranslateService } from '@ngx-translate/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
})
export class AppComponent {

    constructor(private translate: TranslateService) {
+       this.translate.setDefaultLang('en');
+       this.translate.use('en');
    }
}

多言語ファイルを用意する

ディレクトリの構成はこんな感じ。

src
└ assets
  └ language
    ├ app-01
    │ └ en.json
    ├ app-02
    │ └ en.json
    └ common
      └ en.json
app-01/en.json
{
  "おはよう これはapp01だよ": "Good morning this is app01"
}
app-02/en.json
{
  "こんにちは これはapp02だよ": "Hello It's app02"
}
common/en.json
{
  "これは共通だお": "This is common"
}

ちなみに表示する画面はこうだ。
「これは共通だお」はどちらのアプリIDでも翻訳される、残りはアプリIDによって翻訳されるされないが切り替わることが期待される動作。

translate-example.component.html
<p translate>これは共通だお</p>
<p translate>おはよう これはapp01だよ</p>
<p translate>こんにちは これはapp02だよ</p>

確認してみる

まずはアプリIDがapp-01の場合
スクリーンショット 2019-12-29 2.09.30.png

次にアプリIDがapp-02の場合
スクリーンショット 2019-12-29 2.10.24.png

アプリIDによって参照される翻訳ファイルが切り替わることが確認できる。

参考

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?