Core: Json is loaded successfully but texts are not being translated on v8.0.0

Created on 21 Nov 2017  路  10Comments  路  Source: ngx-translate/core

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
Translations are not applied on pipes on the last version (8.0.0).

Expected/desired behavior
Show translated texts on view.

Reproduction of the problem
I've changed my project to support Angular 5.0.2 and ngx-translate 8.0.0 versions, so my loader now injects HttpClient instead of Http and my NgModule imports my HttpClientModule.

export function HttpLoaderFactory (http: HttpClient) {
    return new TranslateHttpLoader(http, baseUrl + 'assets/i18n/', '.json');
}
@NgModule({
    declarations: [
        ...
    ],
    imports: [
        BrowserModule,
        HttpClientModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: HttpLoaderFactory,
                deps: [HttpClient]
            }
        }),
        ...
    ],
    providers: [
        {provide: HTTP_INTERCEPTORS, useClass: HttpApiInterceptor, multi: true},
        ...
    ],
    bootstrap: [ AppComponent ]
})
export class AppModule {
}

The problem is that project builds correctly but now translations are not applied on pipes (view is showing nothing, even the text without translation). The "en.json" file is being loaded successfully.
I've debugged the Pipe's code and it's getting inside it with the correct text but translation value is not changed.

You can see this plunker http://plnkr.co/edit/nFlPoqh9X2yPGMIbxqDH?p=info which is a copy of the official demo of ngx-translate including an interceptor.

What is the expected behavior?
Ngx-translate should translate correctly all the piped texts, as in previous versions.

What is the motivation / use case for changing the behavior?
To detect some future problems with the library.

Please tell us about your environment:

  • ngx-translate version: 8.0.0
  • ngx-translate/http-loader version: 2.0.0
  • Angular version: 5.0.2
  • Browser: all

Most helpful comment

Finally got a solution to make Translation work with HttpInterceptors ..
1-) First change the createTranslateLoader wich depends on HttpClient methods in app.modules.ts to use custom translateHttpLoaderFactory wich depends on HttpBackend .

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

==> By
export function translateHttpLoaderFactory(httpBackend: HttpBackend): TranslateHttpLoader { return new TranslateHttpLoader(new HttpClient(httpBackend)); }

2-) in your app.modules inports array use the new TranslateLoder Factory

=>> replace
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: createTranslateLoader, deps: [HttpClient] } })

==> With
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: translateHttpLoaderFactory, deps: [HttpBackend] } })

and you are ready to go. 馃憤

All 10 comments

Sorry I removed my question, I was just investigating the issue. The problem is when you import the library directly into an interceptor (from constructor). In order to use the library in the interceptor, you must inject it and remove it from the constructor.

Was my fault, i wasn't returning the results on the "map" inside intercept method. So jsons was passing over my interceptor without being exposed.

@Injectable()
export class HttpApiInterceptor implements HttpInterceptor {

    constructor () {
    }

    intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req)
            .map(res => {
                if (res instanceof HttpResponse) {
                    // If response is "204 Not Content" then returns an empty array list
                    if (res.status === 204) {
                        return [];
                    }
                }
                return res;  <--- I wasn't returning nothing here
            });
    }

}

Closed!

@ivandatio
I have same problem. But your solution doesn't helped me.

import {Observable} from 'rxjs/Observable';
import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse, HttpParams, HttpResponse} from '@angular/common/http';
import 'rxjs/add/operator/first';
import {SessionStorageService} from 'ng2-webstorage';
import { ToasterService } from 'angular2-toaster';
import {Router} from '@angular/router';

@Injectable()
export class HttpInterceptorService implements HttpInterceptor {
    private toasterService: ToasterService;

    constructor(
        public router: Router,
        private sessionStorage: SessionStorageService,
        toasterService: ToasterService
    ) {
        this.toasterService = toasterService;
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): any {
        const url = '';
        req = req.clone({
            url: url + req.url,
            // responseType: 'text',//needed to avoid problem witch shows 201 status as error. don't forget to JSON.parse data
            headers: req.headers.set('Authorization', this.sessionStorage.retrieve('access_token'))
        });
        return next.handle(req)
            .map(res => {
                console.log('result', res);
                if (res instanceof HttpResponse) {
                    // If response is "204 Not Content" then returns an empty array list
                    if (res.status === 204) {
                        return [];
                    }
                }
                return res;
            });
    }
}

app.module

...
export function createTranslateLoader(http: HttpClient) {
    return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
...
@NgModule({
    imports: [
        BrowserModule,
        FormsModule,
        HttpClientModule,
        appRouter,
        ToasterModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: createTranslateLoader,
                deps: [Http]
            }
        }),
        AuthorizationModule,
        Ng2Webstorage,
        BsDropdownModule.forRoot(),
        TooltipModule.forRoot(),
        ModalModule.forRoot(),
        SidebarModule.forRoot(),
        BrowserAnimationsModule
    ],
    declarations: [
        AppComponent,
        ...APP_CONTAINERS,
        ...APP_COMPONENTS,
        ...APP_DIRECTIVES
    ],
    providers: [
        {provide: HTTP_INTERCEPTORS, useClass: HttpInterceptorService, multi: true},
        CardService,
        TokenService,
        MainRequestService
    ],
    bootstrap: [AppComponent]
})
export class AppModule {
}

@aitboudad If I'm trying to use your variant. I get

ERROR in http-interceptor.service.ts (16,9): Type 'Observable | H...' is not assignable to type 'Observable>'.
Type 'any[] | HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse | HttpUserEven...' is not assignable to type 'HttpEvent'.
Type 'any[]' is not assignable to type 'HttpEvent'.
Type 'any[]' is not assignable to type 'HttpUserEvent'.
Property 'type' is missing in type 'any[]'.

This is my final intercept method:

intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(req)
            .map(res => {
                if (res instanceof HttpResponse) {
                    // If response is "204 Not Content" then returns an empty array list
                    if (res.status === 204) {
                        const result: any = res;
                        result.body = { data: [] };
                        return result;
                    }
                }
                return res;
            })
}

And I'm seeing that on imports:

TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: createTranslateLoader,
                deps: [Http] <---- It should be HttpClient
            }
        }),

oh. my mistake. i was trying to load translation with old http. and forgot to revert changes,
thx for fast reply.

Hello,
I have a related problem with this topic. HttpLoader has been working well until I add HttpInterceptor service to add header authentication token to my http request. It takes all "translations request" but it is not necessary.

I try to filter http request but it is impossible and it overloads the app.
Any suggestions, please?

headerInterceptorts

```import { Injectable } from '@angular/core';
import {
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpEvent
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
import { mergeMap } from 'rxjs/operators';

@Injectable()
export class HeaderInterceptor implements HttpInterceptor {
constructor(private auth: AuthService) {}

intercept(
request: HttpRequest,
next: HttpHandler
): Observable> {

return this.auth.getToken().pipe(
  mergeMap((token: string) => {
    if (token) {
      // clone and modify the request
      request = request.clone({
        setHeaders: {
          FIREBASE_AUTH_TOKEN: token
        }
      });
    }
    console.log(request);
    return next.handle(request);
  })
);

}
`}

###  app.module.ts

@NgModule({
declarations: [AppComponent],
imports: [
AppRoutingModule,
HttpClientModule,
ReactiveFormsModule,
MaterialModule,
SharedModule.forRoot(),
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient]
}
})
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HeaderInterceptor,
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule {}

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

Finally got a solution to make Translation work with HttpInterceptors ..
1-) First change the createTranslateLoader wich depends on HttpClient methods in app.modules.ts to use custom translateHttpLoaderFactory wich depends on HttpBackend .

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

==> By
export function translateHttpLoaderFactory(httpBackend: HttpBackend): TranslateHttpLoader { return new TranslateHttpLoader(new HttpClient(httpBackend)); }

2-) in your app.modules inports array use the new TranslateLoder Factory

=>> replace
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: createTranslateLoader, deps: [HttpClient] } })

==> With
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: translateHttpLoaderFactory, deps: [HttpBackend] } })

and you are ready to go. 馃憤

@PavelFoujeu You just saved my life. Thank you, you truly are a wonderful human being.

translateHttpLoaderFactory

Finally got a solution to make Translation work with HttpInterceptors ..
1-) First change the createTranslateLoader wich depends on HttpClient methods in app.modules.ts to use custom translateHttpLoaderFactory wich depends on HttpBackend .

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

==> By
export function translateHttpLoaderFactory(httpBackend: HttpBackend): TranslateHttpLoader { return new TranslateHttpLoader(new HttpClient(httpBackend)); }

2-) in your app.modules inports array use the new TranslateLoder Factory

=>> replace
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: createTranslateLoader, deps: [HttpClient] } })

==> With
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: translateHttpLoaderFactory, deps: [HttpBackend] } })

and you are ready to go.

Not working,getting the below error:
core.js:1673 ERROR TypeError: _this.handler.handle is not a function
at MergeMapSubscriber.project (http.js:974)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:61)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:51)
at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:55)
at Observable._subscribe (scalar.js:5)
at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (Observable.js:42)
at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:28)
at MergeMapOperator.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapOperator.call (mergeMap.js:29)
at Observable.push../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:23)
at FilterOperator.push../node_modules/rxjs/_esm5/internal/operators/filter.js.FilterOperator.call (filter.js:15)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bjornharvold picture bjornharvold  路  3Comments

crebuh picture crebuh  路  3Comments

IterationCorp picture IterationCorp  路  3Comments

alkemist picture alkemist  路  3Comments

pndewit picture pndewit  路  3Comments