Skip to content

Angular国际化集成ngx-translate #102

Open
@deepthan

Description

@deepthan

国际化集成ngx-translate

用什么做i18n?

https://stackoverflow.com/questions/51087137/angular-6-i18n-vs-ngx-translate

目前有三种方式

使用ngx-translate做法

  • 首先在app.module中引入此插件的module
import {
  HttpClient
} from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

// i18n
export function createTranslateLoader(http: HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

@NgModule({
  imports: [
    TranslateModule.forRoot({
       loader: {
         provide: TranslateLoader,
         useFactory: createTranslateLoader,
         deps: [HttpClient]
       }
    })
  ],
})
  • 然后在assets文件夹下建一个i18n文件夹,里面新建两个文件

    • en.json

      {
        "home": "HOME"
      }
      
      
    • zh-CN.json

      {
        "home": "首页"
      }
      
  • 再在app.component.ts中设置默认的语言

import { TranslateService } from '@ngx-translate/core';
@Component({
  selector: 'app-root',
  template: `
    <router-outlet></router-outlet>
    <div>{{ 'home' | translate }}</div>
  `,
})
...


export class AppComponent implements OnInit{

  constructor(public translate: TranslatorService) {
    
    
    translate.setDefaultLang('en');
    translate.use('en');
  }
}

这样div里就可以渲染出来

HOME

选择语言类型渲染不同的语言

  • core文件夹下建i18n/i18n.service.ts并注册,提供获取当前语言、设置语言、获取语言列表,并且是存在localstorage中的。
/**
 * 国际化服务部分
 */ 
import { Injectable, Inject, Injector } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, BehaviorSubject } from 'rxjs';
import { filter } from 'rxjs/operators';

import { en_US, zh_CN, NzI18nService } from 'ng-zorro-antd';
import * as df_en from 'date-fns/locale/en';
import * as df_zh_cn from 'date-fns/locale/zh_cn';
import { TranslateService } from '@ngx-translate/core';
import { AlainI18NService } from '@delon/theme';

@Injectable()
export class I18NService implements AlainI18NService {
  private _default = 'zh-CN';
  private change$ = new BehaviorSubject<string>(null);

  private _langs = [
    { code: 'en', text: 'English' },
    { code: 'zh-CN', text: '中文' },
  ];

  constructor(
    private nzI18nService: NzI18nService,
    private translate: TranslateService,
    private injector: Injector,
  ) {
    const defaultLan = this.storedLang() || translate.getBrowserLang();
    const lans = this._langs.map(item => item.code);
    this._default = lans.includes(defaultLan) ? defaultLan : lans[0];
    translate.addLangs(lans);
    this.setZorro(this._default).setDateFns(this._default);
  }

  setZorro(lang: string): this {
    this.nzI18nService.setLocale(lang === 'en' ? en_US : zh_CN);
    return this;
  }

  setDateFns(lang: string): this {
    (window as any).__locale__ = lang === 'en' ? df_en : df_zh_cn;
    return this;
  }

  get change(): Observable<string> {
    return this.change$.asObservable().pipe(filter(w => w != null));
  }

  use(lang: string): void {
    lang = lang || this.translate.getDefaultLang();
    if (this.currentLang === lang) return;
    this.setZorro(lang).setDateFns(lang);
    this.storeLang(lang);
    this.translate.use(lang).subscribe(() => this.change$.next(lang));
  }

  /** 获取语言列表 */
  getLangs() {
    return this._langs;
  }

  /** 翻译 */
  interpret(key: string) {
    return this.translate.instant(key);
  }

  /** 默认语言 */
  get defaultLang() {
    return this._default;
  }

  /** 当前语言 */
  get currentLang() {
    return (
      this.translate.currentLang ||
      this.translate.getDefaultLang() ||
      this._default
    );
  }

  /** 存选中的语言 **/
  storeLang(lang: string) {
    localStorage.setItem("language", lang);
  }

  /** 取存储的语言 **/
  storedLang() {
    return (
      localStorage.getItem("language")
    );
  }
}

  • 不在app.component.ts中设置默认语言,而是新建一个服务,去设置整个项目的默认配置数据。在core下建startup/startup.service.ts
/**
 * 用于应用启动时
 * 一般用来获取应用所需要的基础数据等
 */
import { Injectable, Injector, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { zip } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { I18NService } from '../i18n/i18n.service';

@Injectable()
export class StartupService {
  constructor(
    private translate: TranslateService,
    private i18n: I18NService,
    private injector: Injector,
    private httpClient: HttpClient,
  ) {}

  load(): Promise<any> {
    // 只支持用promise实现
    // https://github.com/angular/angular/issues/15088
    return new Promise((resolve, reject) => {
      zip(
        this.httpClient.get(`assets/i18n/${this.i18n.defaultLang}.json`),
      )
        .pipe(
          // 接收其他拦截器后产生的异常消息
          catchError(([langData]) => {
            resolve(null);
            return [langData];
          }),
        )
        .subscribe(
          ([langData]) => {
            // 设置默认语言
            this.translate.setTranslation(this.i18n.defaultLang, langData);
            this.translate.setDefaultLang(this.i18n.defaultLang);
          },
          () => {},
          () => {
            resolve(null);
          },
        );
    });
  }
}

  • 最后在一个组件里面选择语言
<nz-select style="width: 120px;" [(ngModel)]="selectedValue" nzAllowClear nzPlaceHolder="Choose" (ngModelChange)="changeLang()">
  <nz-option nzValue="en" nzLabel="en"></nz-option>
  <nz-option nzValue="zh-CN" nzLabel="zh-CN"></nz-option>
</nz-select>
import { Component, OnInit } from '@angular/core';

import { I18NService } from '@core/i18n/i18n.service';

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

  constructor(
    private i18NService : I18NService
  ) { }

  selectedValue : ""
  changeLang(){
    this.i18NService.use(this.selectedValue)
  }

}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions