メモです。
環境
- Windows 11 Home 21H2 22000.556
- Angular CLI: 13.2.6
- Node: 16.13.1
- Package Manager: npm 8.3.0
- @ngx-translate/core 14.0.0
- @ngx-translate/http-loader 7.0.0
準備
お試しということで、サンプルアプリ に ローカライゼーション を実装していきます。

まず ZIP をダウンロードして、展開して、デバッグ実行ができる状態まで進めておきます。

手順
インストール
次のコマンドで npmモジュール をインストールします。
npm install @ngx-translate/core --save
npm install @ngx-translate/http-loader --save
実装
「src\app\app.module.ts」を次のように修正します。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './in-memory-data.service';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
import { HeroesComponent } from './heroes/heroes.component';
import { HeroSearchComponent } from './hero-search/hero-search.component';
import { MessagesComponent } from './messages/messages.component';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
@NgModule({
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient]
},
defaultLanguage: 'en'
}),
// HttpClientInMemoryWebApiModule.forRoot(
// InMemoryDataService, { dataEncapsulation: false }
// )
],
declarations: [
AppComponent,
DashboardComponent,
HeroesComponent,
HeroDetailComponent,
MessagesComponent,
HeroSearchComponent
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(translate: TranslateService) {
translate.use('ja');
}
}

翻訳の設定
後は翻訳の設定を書いていくだけです。
「src\assets\i18n\」に、読み込む翻訳JSONを作成します。
今回は「ja.json」と「en.json」をそれぞれ作りました。
{
"Dashboard": "ダッシュボード",
"Heroes": "ヒーローズ",
"Tour of Heroes": "ツアー・オブ・ヒーローズ",
"Top Heroes": "上位ヒーローズ",
"Hero Search": "ヒーロー検索"
}

HTML内に翻訳を埋め込む場合は、次ように修正します。
<h1>{{title}}</h1>
<nav>
<a routerLink="/dashboard" translate>{{'Dashboard'}}</a>
<a routerLink="/heroes" translate>{{'Heroes'}}</a>
</nav>
<router-outlet></router-outlet>
<app-messages></app-messages>

TSから翻訳する場合は、次のように修正します。
import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title: string = '';
constructor(private translate: TranslateService) {
this.translate.get('Tour of Heroes').subscribe((res: string) => {
this.title = res;
});
}
}

確認
上記修正をすると、次のように表示されます。

キャッシュバスティング
翻訳JSONをキャッシュバスティングに対応させます。
「src\app\app.module.ts」を次のように修正することで、ページを開くと新たな翻訳JSONを取得するようになります。
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
↓↓↓
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json?cb=' + new Date().getTime());
}

実行してみるとこんな感じに、毎回取得しているのが分かると思います。

理想を言えばビルドやデプロイ毎で、キャッシュバスティングされればいいのですが、Angular にはその機能がないようです。
今後のアップデートに期待します。
躓いた点
./assets/i18n/en.json 404 Not Found
次のエラーが出て、翻訳JSONが取得できなかった。
ERROR {body: {…}, url: './assets/i18n/en.json', headers: HttpHeaders, status: 404, statusText: 'Not Found'}

解決
「src\app\app.module.ts」内で HttpClientInMemoryWebApiModule が読み込まれているとエラーになるみたいなので、コメントアウトしました。

Invalid version: “15.2-15.3”
次のエラーが出て、build ができなかった。
PS D:\Angular\toh-pt6> npm run build
> [email protected] build
> ng build
⠙ Generating browser application bundles (phase: setup)...Processing legacy "View Engine" libraries:
- angular-in-memory-web-api [module/esm5] (git+https://github.com/angular/in-memory-web-api.git)
Encourage the library authors to publish an Ivy distribution.
✔ Browser application bundle generation complete.
An unhandled exception occurred: Transform failed with 1 error:
error: Invalid version: "15.2-15.3"
See "C:\Users\*****\AppData\Local\Temp\ng-jJmYje\angular-errors.log" for further details.

[error] HookWebpackError: Transform failed with 1 error:
error: Invalid version: "15.2-15.3"
at makeWebpackError (D:\Angular\toh-pt6\node_modules\webpack\lib\HookWebpackError.js:48:9)
at D:\Angular\toh-pt6\node_modules\webpack\lib\Compilation.js:3055:12
at eval (eval at create (D:\Angular\toh-pt6\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:98:1)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
-- inner error --
Error: Transform failed with 1 error:
error: Invalid version: "15.2-15.3"
at failureErrorWithLog (D:\Angular\toh-pt6\node_modules\esbuild\lib\main.js:1557:15)
at D:\Angular\toh-pt6\node_modules\esbuild\lib\main.js:1346:29
at D:\Angular\toh-pt6\node_modules\esbuild\lib\main.js:637:9
at handleIncomingPacket (D:\Angular\toh-pt6\node_modules\esbuild\lib\main.js:734:9)
at Socket.readFromStdout (D:\Angular\toh-pt6\node_modules\esbuild\lib\main.js:604:7)
at Socket.emit (node:events:390:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10)
at Pipe.onStreamRead (node:internal/stream_base_commons:199:23)
解決
「@angular-devkit/build-angular」を 13.2.6 にアップデートしたらビルドできた。
npm update @angular-devkit/[email protected]

参考
GitHub - ngx-translate/core: The internationalization (i18n) library for Angular
The internationalization (i18n) library for Angular - GitHub - ngx-translate/core: The internationalization (i18n) library for Angular