3

我想扩展 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:

应用程序模块:

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 { }

(上面的代码取自这里

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

4

5 回答 5

2

如果你做管道不纯的工作......但我认为这不是解决这个问题的最佳方法。

@Pipe({
  name: 'msg',
  pure: false
})
export class TranslationPipe extends TranslatePipe {
于 2018-07-18T13:19:13.650 回答
1

You do not any extra library for translations. As an example, you only need a pipe file translation-pipe.ts file and translation.provder.ts file and you can extend whatever you want. Please check the below files

translation-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); }
}

Here private translate() function is main function to change the local key to language. You can import local files like en.ts, sp.ts, au.ts etc. or you can modify this function to connect database and get the key value pairs... Example of local translation file is

en.ts

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

or

tr.ts

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

Have a nice coding...

于 2017-09-26T16:53:16.937 回答
0

来自不纯TranslatePipengx-translate这是有原因的。所以你也必须设置purefalse

@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()会将管道标记为脏以请求重新渲染。

于 2021-07-16T13:18:08.707 回答
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])
    );
  }
}
于 2021-03-15T09:55:51.347 回答
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 代替。

于 2020-11-20T13:59:16.527 回答