Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong TranslateHttpLoader after upgrade app to Angular 17 #1470

Open
icolumbro-asf opened this issue Feb 14, 2024 · 1 comment
Open

Wrong TranslateHttpLoader after upgrade app to Angular 17 #1470

icolumbro-asf opened this issue Feb 14, 2024 · 1 comment

Comments

@icolumbro-asf
Copy link

Yesterday I upgraded my app to Angular 17now I get error TypeError: translateService.currentLoader.initialize is not a function, this is my code:

startup.module.ts

import {
  ICultureConfiguration,
  CULTURE_CONFIGURATION_TOKEN,
} from '../types/model';
import {
  TranslateLoader,
  TranslateModule,
  TranslateService,
} from '@ngx-translate/core';
import { CultureService } from '../services/culture.service';
import { firstValueFrom } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { InMemoryTranslateHttpLoader } from '../services/in-memory-translate-loader';
import { NgModule, ModuleWithProviders, APP_INITIALIZER } from '@angular/core';
import { SpinnerService } from '../services/spinner.service';
import { tap } from 'rxjs/operators';
import { StorageService } from '../services/storage.service';
import { DialogService } from '../services/dialog.service';

export function httpLoaderFactory(
  http: HttpClient,
  cultureConfiguration: ICultureConfiguration
) {
  return new InMemoryTranslateHttpLoader(http, cultureConfiguration);
}

export const translateModule = TranslateModule.forRoot({
  loader: {
    provide: TranslateLoader,
    useFactory: httpLoaderFactory,
    deps: [HttpClient, CULTURE_CONFIGURATION_TOKEN],
  },
});

@NgModule({
  declarations: [],
  imports: [translateModule],
  exports: [],
  providers: [CultureService, DialogService, SpinnerService, StorageService],
})
export class StartupModule {
  public static forRoot(
    cultureConfiguration: ICultureConfiguration
  ): ModuleWithProviders<StartupModule> {
    return {
      ngModule: StartupModule,
      providers: [
        {
          provide: CULTURE_CONFIGURATION_TOKEN,
          useValue: cultureConfiguration,
          multi: false,
        },
        {
          provide: APP_INITIALIZER,
          useFactory: languageLoader,
          deps: [TranslateService, CultureService],
          multi: true,
        },
      ],
    };
  }
}

export function languageLoader(
  translateService: TranslateService,
  cultureService: CultureService
) {
  return function () {
    return firstValueFrom(
      (<InMemoryTranslateHttpLoader>translateService.currentLoader)
        .initialize()
        .pipe(
          tap((t) => {
            cultureService.initialize();
          })
        )
    );
  };
}

in-memory-translate-loader.ts

import '../extensions-methods/array.extensions';
import '../extensions-methods/form.extensions';
import { all } from 'deepmerge';
import { HttpClient } from '@angular/common/http';
import { ICultureConfiguration } from '../types/model';
import { Injectable } from '@angular/core';
import { map, tap } from 'rxjs/operators';
import { Observable, forkJoin, of } from 'rxjs';
import { TranslateLoader } from '@ngx-translate/core';

@Injectable()
export class InMemoryTranslateHttpLoader extends TranslateLoader {
  private _data: TranslationResult[] = [];

  constructor(
    private _httpClient: HttpClient,
    private _cultureConfiguration: ICultureConfiguration
  ) {
    super();
  }

  public initialize = (): Observable<TranslationResult[]> => {
    let httpCalls: Observable<any>[] = [];
    for (let i = 0; i < this._cultureConfiguration.resourcePaths.length; i++) {
      for (let x = 0; x < this._cultureConfiguration.cultureCodes.length; x++) {
        let url = this._cultureConfiguration.resourcePaths[i].replace(
          '{code}',
          this._cultureConfiguration.cultureCodes[x]
        );
        httpCalls.push(
          this._httpClient
            .get(url)
            .pipe(
              map(
                (result) =>
                  new TranslationResult(
                    this._cultureConfiguration.cultureCodes[x],
                    result
                  )
              )
            )
        );
      }
    }
    return forkJoin(httpCalls).pipe(
      tap((results: TranslationResult[]) => {
        this._data = results
          .groupBy((g) => g.cultureCode)
          .map((m) => {
            let innerResource = new TranslationResult(m.key, {});
            m.items.push(innerResource);
            let mergedItems = all(m.items.map((m) => m.data));
            return new TranslationResult(m.key, mergedItems);
          });
      })
    );
  };

  public getTranslation(lang: string): Observable<any> {
    let ret = this._data.find((f) => f.cultureCode == lang).data;
    return of(ret);
  }
}

export class TranslationResult {
  constructor(public cultureCode: string, public data: any) {}
}

in Angular 16 httpLoaderFactory function is executed before languageLoader while in Angular 17 languageLoader is executed leading to the given error...

@dharma-code-chris
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants