core: Error: No provider for TranslatePipe!

I’m submitting a … (check one with “x”)

[x] bug report => check the FAQ and search github for a similar issue or PR before submitting
[ ] support request => check the FAQ and search github for a similar issue before submitting
[ ] feature request

Current behavior

When trying to inject TranslatePipe (in another Pipe, as an helper), I get the error “Error: No provider for TranslatePipe!”

Expected/desired behavior

We should be able to either inject the Pipe, or have a service/proper Injectable doing the similar heavy lifting to allow easier integration with custom pipes

Reproduction of the problem http://plnkr.co/edit/Yjh9qLSzLSfCWI77xW3f?p=info

What is the motivation / use case for changing the behavior? Chaining pipes is nice, but troublesome. being able to have a single pipe taking care of everything would be much better. If we can’t, we will ALWAYS end up doing 'my-value' | customPipe | translate. It’s a pain.

Please tell us about your environment:

  • ngx-translate version: 7.0.0
  • Angular version: 4.1.3
  • Browser: all

PS: I consider this a bug as it’s been advised previously to inject the pipe in a service or another pipe. Plus the pipe is tagged as @Injectable, so I expect to be able to inject it.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 9
  • Comments: 20

Most upvoted comments

One more way

import { TranslatePipe } from "@ngx-translate/core";

@Component({
    selector: '',
    templateUrl: '',
    providers: [TranslatePipe]
})

Why not use the translate service instant method instead which is synchronous and doesn’t use an observable?

And I replied to your questions, you can’t declare it at app level because the pipe uses ChangeDetectorRef which is for components and directives. What kind of design is this? The one from the Angular team.

I also faced the same issue. This is how I solved:

@Pipe({ name: 'customPipe', pure: false })
export class CustomPipe implements PipeTransform {
    translatePipe: TranslatePipe;

    constructor(translate: TranslateService, _ref: ChangeDetectorRef) {
        this.translatePipe = new TranslatePipe(translate, _ref);
    }

    transform(value: any): string {

        return `${this.translatePipe.transform(value)}`;
    }
}

Notice that I followed @lemoinem 's solution, but in my case I had to set the pure flag of the pipe false. Because in my case it wasn’t detect the changes (when user was selecting another language from a drop down).

You need to make the pipe aware of language changes. See the pseudocode below (I haven’t run it but hopefully it can lead you in the right direction). It’s based on how the translate pipe is implemented:

@Pipe({
  name: 'customTranslate',
  pure: false
})
export class CustomTranslate implements PipeTransform, OnDestroy {
  private langChangeSubscription: Subscription;
  private value: string;
  private lastQuery: string;
  private lastParams: any;
  private lastLang: string;

  constructor(private translate: TranslateService, private cdr: ChangeDetectorRef) {
    this.langChangeSubscription = translate.onLangChange.pipe(
      takeUntil(this.destroy$)
    ).subscribe(() => {
      this.cdr.markForCheck();
    });
  }

  ngOnDestroy() {
    this.langChangeSubscription.unsubscribe();
  }

  transform(query: string, params: any): string {
    if (equals(query, this.lastQuery) && equals(params, this.lastParams) && equals(this.translate.currentLang, this.lastLang)) {
      return this.value;
    }
    this.lastQuery = query;
    this.lastParams = params;
    this.lastLang = this.translate.currentLang;
    this.translate.get(query, params).subscribe((result) => {
      this.value = result;
      this.cdr.markForCheck();
    });
  }
}

Why can’t we declare this provider at the app level ? Why must I declare it at each component ? What kind of design is that ?

I’m using Angular 4, if you provide the pipe in the module, you can then import it and use it within another pipe where needed.

@samoilenko how do you use your own provider for the pipe? I am having the same issue