如何扩展ngx-translate管道

时间:2017-09-26 16:39:45

标签: angular angular-pipe ngx-translate

我想扩展ngx-translate管道,使其在我的应用程序中具有多种用途。

我的烟斗:

import { Pipe, PipeTransform } from '@angular/core';
import { TranslatePipe } from "@ngx-translate/core";

@Pipe({
  name: 'msg'
})

export class MsgPipe extends TranslatePipe implements PipeTransform {
  transform(value: any, args: any[]): any {
    return super.transform(value, args)
  }
}

为了等待加载相关的翻译模块,我使用了Angular的APP_INITIALIZER:

app.module:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { appRoutes } from './app.routes';
import { AppComponent } from './root/app.component';
import { PageNotFoundComponent } from './shared/components/page-not-found/page-not-found.component';
import { HomePageComponent } from './shared/components/home-page/home-page.component';
import { MsgPipe } from './shared/pipes/msg.pipe';
import { ChangeDetectorRef } from '@angular/core';
import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { Injector, APP_INITIALIZER } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { LOCATION_INITIALIZED } from '@angular/common';

export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http);
}


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 langToSet = 'en'
              translate.setDefaultLang('en');
            translate.use(langToSet).subscribe(() => {
                console.info(`Successfully initialized '${langToSet}' language.'`);
            }, err => {
                console.error(`Problem with '${langToSet}' language initialization.'`);
            }, () => {
                resolve(null);
            });
        });
    });
}

@NgModule({
    declarations: [
        AppComponent,
        PageNotFoundComponent,
        HomePageComponent,
        MsgPipe
    ],
    imports: [
        BrowserModule,
        RouterModule.forRoot(appRoutes),
        HttpClientModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: HttpLoaderFactory,
                deps: [HttpClient]
            }
        }),
    ],
    providers: [
        {
            provide: APP_INITIALIZER,
            useFactory: appInitializerFactory,
            deps: [TranslateService, Injector],
            multi: true
        }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

(上面的代码取自here

除非将pure设置为false,否则我的管道仍无法正常工作,从而导致多次不必要的调用。没有错误,它只是没有改变内容。

5 个答案:

答案 0 :(得分:0)

您没有任何额外的翻译库。例如,您只需要一个管道文件translation-pipe.ts文件和translation.provder.ts文件,您可以扩展您想要的任何内容。请检查以下文件

<强>翻译-pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

import {TranslateProvider} from '../../providers/translate/translate';

@Pipe({
  name: 'translation',
})
export class TranslationPipe implements PipeTransform {

  constructor(private _translateService: TranslateProvider) { }

  transform(value: string, ...args) {
    return this._translateService.instant(value);
  }
}

<强> TranslateProvider.ts

import {Injectable} from '@angular/core';
import {LANG_EN_TRANS} from './languages/en';
import {LANG_TR_TRANS} from './languages/tr';

@Injectable()
export class TranslateProvider {

  private _currentLang: string;
  // If you want to use dictionary from local resources
  private _dictionary = {
    'en': LANG_EN_TRANS,
    'tr': LANG_TR_TRANS
  };

  // inject our translations
  constructor( private _db: DbProvider) { }

  public get currentLang() {
     if ( this._currentLang !== null) {
       return this._currentLang;
     } else return 'en';
  }

  public use(lang: string): void {
    this._currentLang = lang;
  } // set current language

  // private perform translation
  private translate(key: string): string {

   // if u use local files
    if (this._dictionary[this.currentLang] && this._dictionary[this.currentLang][key]) {
      return this._dictionary[this.currentLang][key];
    } else {
      return key;
    }

   // if u do not want local files then get a json file from database and add to dictionary
  }

  public instant(key: string) { return this.translate(key); }
}

这里private translate()函数是将本地密钥更改为语言的主要功能。您可以导入本地文件,如en.ts,sp.ts,au.ts等,或者您可以修改此功能以连接数据库并获取键值对... 本地翻译文件的示例是

<强> en.ts

export const LANG_EN_TRANS = {
  'about': 'About',
}

<强> tr.ts

export const LANG_TR_TRANS = {
  'about': 'Hakkinda',
}

有一个很好的编码...

答案 1 :(得分:0)

如果您使用管道不纯净的方法...但是我认为这不是解决该问题的最佳方法。

@Pipe({
  name: 'msg',
  pure: false
})
export class TranslationPipe extends TranslatePipe {

答案 2 :(得分:0)

translatepipe本身是不纯正的(请参见:https://github.com/ngx-translate/core/blob/master/projects/ngx-translate/core/src/lib/translate.pipe.ts),因为它需要对可观察到的翻译内容做出反应。

您还应该只调用super.transform(key,... args)而不是Instant(...)。这种方法在我们的项目中起作用。或请说明为什么需要使用Instant。

答案 3 :(得分:0)

接受字符串枚举数组并将其转换为翻译字符串数组的管道示例

import { ChangeDetectorRef, Pipe, PipeTransform } from '@angular/core';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { AlertEnum } from '../alert.enum';

@Pipe({
  name: 'translateAlertArray',
  pure: false
})
export class TranslateErrorsArrayPipe
  extends TranslatePipe
  implements PipeTransform {
  constructor(
    private translateService: TranslateService,
    private changeDetectionRef: ChangeDetectorRef
  ) {
    super(translateService, changeDetectionRef);
  }

  transform(alerts: any): string[] {
    return alerts?.map((alert: AlertEnum) =>
      super.transform('alerts.' + AlertEnum[alert])
    );
  }
}

答案 4 :(得分:0)

来自 TranslatePipengx-translate 不纯。这是有原因的。因此,您也必须将 pure 设置为 false

@Pipe({
  name: 'msg',
  pure: false
})

现在虽然这足以让您使用,但我会稍微扩展一下我的答案。

翻译管道的设计并非只翻译一次就完成。即使您预先加载了一种或什至多种语言的翻译,用户也可以稍后切换语言。实际上,截至今天,您必须处理 3 个不同的事件:

  • 语言更改
  • 默认语言更改
  • 和翻译发生变化

现在,如果您查看原始翻译管道的来源,您会看到,他们已经更新了这些事件的翻译值。每个事件都会调用 updateValue() 方法。见https://github.com/ngx-translate/core/blob/master/projects/ngx-translate/core/src/lib/translate.pipe.ts。然后 updateValue() 会将管道标记为脏以请求重新渲染。