ngx-translate / http-loader

A loader for ngx-translate that loads translations with http calls
MIT License
191 stars 69 forks source link

Unable to use TranslateLoader in Angular 7 #66

Closed ramoncarreras closed 5 years ago

ramoncarreras commented 5 years ago

Current behavior

When I use http-loader to load translations from my API, my APP crashes with the following error displayed on the console:

image

"this.textApi.list" is the method I call when I overwrite TranslateLoader::getTranslation()

Minimal reproduction of the problem with instructions

My app.module.ts looks like this:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { NgxWebstorageModule } from 'ngx-webstorage';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { Insomnia } from '@ionic-native/insomnia/ngx';
import { Device } from '@ionic-native/device/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { ComponentsModule } from './components/components.module';
import { TranslateLoaderService } from './services/translate-loader/translate-loader.service';

@NgModule({
    declarations: [
        AppComponent,
    ],
    entryComponents: [],
    imports: [
        BrowserModule,
        IonicModule.forRoot({
            backButtonText: '',
            backButtonIcon: 'ios-arrow-back',
            spinner: 'dots',
            refreshingSpinner: 'dots',
            loadingSpinner: 'dots',
            infiniteLoadingSpinner: 'dots',
        }),
        NgxWebstorageModule.forRoot({prefix: 'tax-rd', separator: '.'}),
        AppRoutingModule,
        ComponentsModule,
        HttpClientModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useClass: TranslateLoaderService,
                deps: [HttpClient],
            },
        }),
    ],
    providers: [
        SplashScreen,
        Insomnia,
        Device,
        {provide: RouteReuseStrategy, useClass: IonicRouteStrategy},
    ],
    bootstrap: [AppComponent],
})
export class AppModule {
}

And, this is my TranslateLoaderService:

import { Injectable } from '@angular/core';
import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs';
import { TextApiService } from '../../api/text-api/text-api.service';

@Injectable({
    providedIn: 'root',
})
export class TranslateLoaderService implements TranslateLoader {

    constructor(
        private textApi: TextApiService,
    ) {
    }

    getTranslation(langId: string): Observable<any> {
        return this.textApi.list(langId);
    }
}

Finally, this is my TextApiService...

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

import { ClientApiService } from '../client-api/client-api.service';

@Injectable({
    providedIn: 'root',
})
export class TextApiService extends ClientApiService {

    list(idiomaId: string): Observable<any> {
        return this.get('/idiomas', null, idiomaId);
    }

}

... and my ClientApiService (only get method is copied to simplify):

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http';
import { HttpParamsOptions } from '@angular/common/http/src/params';
import { Observable, throwError } from 'rxjs';
import { catchError, share, timeout } from 'rxjs/operators';

import { SERVER_URL } from '../../../environments/environment';

@Injectable({
    providedIn: 'root',
})
export class ClientApiService {

    private acceptLanguage: string;   
    private readonly timeout: number;

    constructor(
        private http: HttpClient,
    ) {
        this.acceptLanguage = 'es';
        this.timeout = 8000;
    }

    get(endpoint, searchParams?: HttpParams | string | any, acceptLanguage?: string): Observable<any> {
        const requestOptions = this.getRequestOptions(acceptLanguage || this.acceptLanguage);

        if (searchParams) {
            if (searchParams instanceof HttpParams) {
                requestOptions.params = searchParams;
            } else {
                if (searchParams instanceof Object) {
                    requestOptions.params = new HttpParams({
                        fromObject: searchParams,
                    } as HttpParamsOptions);
                } else if (typeof searchParams === 'string') {
                    requestOptions.params = new HttpParams({
                        fromString: searchParams,
                    } as HttpParamsOptions);
                }
            }
        }

        return this.http
            .get(this.getEndpoint(endpoint), requestOptions)
            .pipe(
                timeout(this.timeout),
                share(),
                catchError(this.handleError()),
            );
    }

   [...]

}

Environment


ngx-translate/core version: 11.0.1
ngx-translate/http-loader version: 4.0.0
Angular version: 7.2.13
Ionic version: 4.3.1

So, I'm doing something wrong or there is a bug on ngx-translate?

Any help will be appreciated. Thanks.

ramoncarreras commented 5 years ago

My fault, changing my app.module.ts to this makes translation work:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { NgxWebstorageModule } from 'ngx-webstorage';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { Insomnia } from '@ionic-native/insomnia/ngx';
import { Device } from '@ionic-native/device/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { ComponentsModule } from './components/components.module';
import { TranslateLoaderService } from './services/translate-loader/translate-loader.service';

@NgModule({
    declarations: [
        AppComponent,
    ],
    entryComponents: [],
    imports: [
        BrowserModule,
        IonicModule.forRoot({
            backButtonText: '',
            backButtonIcon: 'ios-arrow-back',
            spinner: 'dots',
            refreshingSpinner: 'dots',
            loadingSpinner: 'dots',
            infiniteLoadingSpinner: 'dots',
        }),
        NgxWebstorageModule.forRoot({prefix: 'tax-rd', separator: '.'}),
        AppRoutingModule,
        ComponentsModule,
        HttpClientModule,
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useClass: TranslateLoaderService,
            },
        }),
    ],
    providers: [
        SplashScreen,
        Insomnia,
        Device,
        {provide: RouteReuseStrategy, useClass: IonicRouteStrategy},
    ],
    bootstrap: [AppComponent],
})
export class AppModule {
}