angular中使用ngx-translate国际化配置

一、ngx-translate认识

ngx-translate:The internationalization (i18n) library for Angular.

二、安装

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

三、项目中配置使用ngx-translate

TranslateModule引入到应用的根模块ngModule

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {TranslateModule} from '@ngx-translate/core';
import { HttpModule, Http } from '@angular/http';	//注意:这是angular版本低于4.3引入方法,以后都以此替代,import {HttpClientModule, HttpClient} from '@angular/common/http';

// AoT requires an exported function for factories
export function HttpLoaderFactory(http: Http) {
    return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

@NgModule({
    imports: [
        BrowserModule,
        HttpModule,
        TranslateModule.forRoot({
        	defaultLanguage: 'en',
            loader: {
                provide: TranslateLoader,
                useFactory: HttpLoaderFactory,
                deps: [Http]
            }
        })
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts中引入TranslateService

import {Component} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';

@Component({
    selector: 'app',
    template: `
        
{{ 'Add' | translate }}
`
}) export class AppComponent { lang: string = ''; constructor(translate: TranslateService) { if (this.storageService.getCurrentLang() !== undefined) { this.lang = this.storageService.getCurrentLang(); } else { const browserLang = this.translate.getBrowserLang(); this.lang = browserLang === 'zh' ? 'zh' : 'en'; } this.translate.setDefaultLang(this.lang); this.translate.use(this.lang); } selectLanguage(lang: strting): void { localStorage.setItem('currentLanguage', lang); this.translate.use(lang); } }

assets/i18n目录下增加国际化json文件

{	//zh.json
  "Add": "增加",
  "About": "***有限公司(C) 2014-2020"
}
{	//en.json
  "Add": "add",
  "About": "*** Corporation. All rights reserved.(C)2014-2020"
}

至此,在HTML中通过管道的方式国际化功能已经实现,但是有个新疑问?
typescript文件中使用国际化会怎么样??
如下在app.component.htmlapp.component.ts中增加如下代码:

<h2>{{title}}h2>
ngOnInit() {
    this.title = this.translate.instant('About');
  }About

保存运行后,会发现About根本没有国际化,显示还是为About ??

angular中使用ngx-translate国际化配置_第1张图片
在此猜想应该字典文件没有拉取到,于是查看官网,解释如下:

translate.instant()是同步的,默认文件加载器是异步的。您有责任知道何时加载翻译,使用此方法是安全的。如果不确定,则应改用该get方法。

于是将translate.instant()改成translate.get()异步的方式:

ngOnInit() {
    this.translate.get('About').subscribe( value => {
      this.title = value;
    });
}

运行后效果如下:

angular中使用ngx-translate国际化配置_第2张图片
可以看出,页面加载时可以正常显示,关于HTML中为啥能够直接国际化,这涉及到angular变更检测知识,有兴趣可以下去了解下。实践过的码农就会发现,切换中英文切换不了,这又是什么问题呢??

通过查询资料,找到两种解决这个问题的方法:

方法一:全局监听

 this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
      this.title = this.translate.instant('AddSuccess');
});

通过onLangChange()可以全局监听语言的变化,虽然功能可以实现,但是心细的小可爱就会发现,这在实际中根本不能解决问题,后面工程原来越大,难道你在ts中新增一个国际化就要监听一下???
方法二:刷新页面
修改selectLanguage()函数为如下:

 selectLanguage(lang: strting): void {
    localStorage.setItem('currentLanguage', lang);
    window.location.reload();
 }

现在你进行中英文切换时就会发现,页面点击中英文切换页面会刷新一下,说下在实际应用中这种方法的弊端:

  1. 当项目过大时,点击切换中英文,页面刷新会很慢,而第一种方法好处就在于不用刷新页面可以直接却换;
  2. 因为在实际的开发过程中多使用的是translate.instant()方法,点击切换中英文时,虽然页面刷新,但是还是存在字典文件未拉取到,国际化不成功情况,解决方法如下:

app.Module.ts中增加如下代码:

import { Injector, APP_INITIALIZER } from '@angular/core';
import { LOCATION_INITIALIZED } from '@angular/common';

export function appInitializerFactory(translate: TranslateService, injector: Injector) {
  return () => new Promise<any>((resolve: any) => {
    const locationInitialized = injector.get(LOCATION_INITIALIZED, Promise.resolve(null));
    locationInitialized.then(() => {
      const lang = translate.getBrowserLang() === 'zh' ? 'zh' : 'en';
      translate.setDefaultLang(lang);
      translate.use(lang).subscribe(() => {
        console.info(`Successfully initialized '${lang}' language.'`);
      }, err => {
        console.error(`Problem with '${lang}' language initialization.'`);
      }, () => {
        resolve(null);
      });
    });
  });
}

@NgModule({
  declarations: [...],
  imports: [...],
  providers: [{
      provide: APP_INITIALIZER,
      useFactory: appInitializerFactory,
      deps: [TranslateService, Injector],
      multi: true
    }],
  bootstrap: [AppComponent]
})

至此,在ts中国际化不成功的问题虽然解决,但是最完美的解决方案,本意是在不刷新页面的情况下实现国际化,但是最终未能解决,终是一大遗憾,如果各位道友有解决方法,欢迎下发留言,感谢!!

你可能感兴趣的:(angular)