core icon indicating copy to clipboard operation
core copied to clipboard

Support for Angular v17

Open kgish opened this issue 8 months ago • 32 comments

I have updated our company application to angular v17 and unfortunately cannot get ngx-translate working.

The problem is that ngModule is no longer used so one has to modify the app.config.ts file.

This is a show-stopper for us, so hopefully this can be fixed soon.

Thanks in advance for your help.

kgish avatar Dec 01 '23 19:12 kgish

What do you mean ngModule is no longer used?

ocombe avatar Dec 01 '23 20:12 ocombe

Maybe this helps, this works for me, although in a small toy-level app:

in your app.config.ts

// required for AoT 
export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

export const appConfig: ApplicationConfig = {
  providers: [provideAnimations(), provideHttpClient(),
    TranslateModule.forRoot({
      defaultLanguage: 'en',
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    }).providers!]
};

Note the ! at the end (basically casts away or suppresses the potential undefined)

Here is the relevant package.json

    "@ngx-translate/core": "^15.0.0",
    "@ngx-translate/http-loader": "^8.0.0"

Now I can just use the pipe for example in a template. Your component needs to import the TranslateModule.

siloimwald avatar Dec 02 '23 19:12 siloimwald

I am using angular17 when trying to use the translation key with translate pip it gets back the error translate pip does not exist Screenshot from 2023-12-03 12-31-10

and this configuration Screenshot from 2023-12-03 12-32-18

ahmedalmorsy1993 avatar Dec 03 '23 10:12 ahmedalmorsy1993

Thanks, now working!

kgish avatar Dec 03 '23 10:12 kgish

Thanks, now working!

should I update my project now to work with me?

ahmedalmorsy1993 avatar Dec 03 '23 10:12 ahmedalmorsy1993

@ahmedalmorsy1993 that's a nice workaround though .providers! is a little hazardous. Angular 17 provides importProdiversFrom to help with 👍

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(appRoutes),
    importProvidersFrom([
      HttpClientModule, 
      TranslateModule.forRoot(provideTranslation())
    ]),
  ],
};

where provideTranslation() pull the set up from (e.g.)

export const provideTranslation = () => ({
  defaultLanguage: 'en',
  loader: {
    provide: TranslateLoader,
    useFactory: TranslateLoaderFactory,
    deps: [HttpBackend],
  },
});

eskwisit avatar Dec 03 '23 21:12 eskwisit

Even better, thanks!

kgish avatar Dec 04 '23 07:12 kgish

@ahmedalmorsy1993 did you manage to fix the html and how?

platinumsolutionsithelp avatar Dec 13 '23 23:12 platinumsolutionsithelp

@ahmedalmorsy1993 did you manage to fix the html and how?

Yes it's working now so this issue can be closed.

kgish avatar Dec 14 '23 12:12 kgish

@ahmedalmorsy1993 you have not imported pipe/module containing pipe in your standalone component.

gultyayev avatar Dec 26 '23 19:12 gultyayev

i updated my project to angular 17 and getting errors for translate pipe and many other. "@ngx-translate/core": "^15.0.0","angularx-qrcode": "^17.0.0", image image

ShailaPatilacmeconnect avatar Jan 09 '24 07:01 ShailaPatilacmeconnect

Here is how it worked for me... app.config.ts

// AoT requires an exported function for factories
export function HttpLoaderFactory(httpClient: HttpClient) {
  return  new  TranslateHttpLoader(httpClient, './assets/i18n/', '.json');
}

export const provideTranslation = () => ({
  defaultLanguage: 'en',
  loader: {
    provide: TranslateLoader,
    useFactory: HttpLoaderFactory,
    deps: [HttpClient],
  },
});

export const appConfig: ApplicationConfig = {
  providers: [
    provideAnimations(), // required animations providers
    provideHttpClient(),
    importProvidersFrom([
      HttpClientModule, 
      TranslateModule.forRoot(provideTranslation())
    ]),
    provideRouter(routes),
    
  ]
};

hpardess avatar Jan 12 '24 23:01 hpardess

I get following issue:

compiler_facade.ts:32 JIT compilation failed for injectable class _TranslateFakeLoader extends TranslateLoader { getTranslation(lang) { return of({}); }

image

muhamedkarajic avatar Jan 18 '24 07:01 muhamedkarajic

Maybe this helps, this works for me, although in a small toy-level app:

in your app.config.ts

// required for AoT 
export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

export const appConfig: ApplicationConfig = {
  providers: [provideAnimations(), provideHttpClient(),
    TranslateModule.forRoot({
      defaultLanguage: 'en',
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    }).providers!]
};

Note the ! at the end (basically casts away or suppresses the potential undefined)

Here is the relevant package.json

    "@ngx-translate/core": "^15.0.0",
    "@ngx-translate/http-loader": "^8.0.0"

Now I can just use the pipe for example in a template. Your component needs to import the TranslateModule.

This dose not solve my issue. Error thrown is:

No provider for TranslateService!

I have also tried to exactly recode everything but I get the same error as before JIT compilation failed for injectable class _TranslateFakeLoader. Sample Code:


export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

appConfig.providers = [
  provideHttpClient(),
  TranslateModule.forRoot({
    defaultLanguage: 'en',
    loader: {
      provide: TranslateLoader,
      deps: [HttpClient],
      useFactory: HttpLoaderFactory
    }
  }).providers!,
]

bootstrapApplication(AppComponent, appConfig).catch((err) =>
  console.error(err)
);

muhamedkarajic avatar Jan 18 '24 07:01 muhamedkarajic

Any news on this?

muhamedkarajic avatar Feb 06 '24 08:02 muhamedkarajic

This dose not solve my issue. Error thrown is:

No provider for TranslateService!

@muhamedkarajic Did you do the import of TranslateModule in the components where you want to use the pipe?

At TS:

import {Component} from '@angular/core';
import {TranslateModule} from '@ngx-translate/core'; <----- this


@Component({
  selector: 'app-home',
  standalone: true,
  imports: [TranslateModule],
  templateUrl: './home.component.html',
  styleUrl: './home.component.scss'
})
export class HomeComponent {

}

At HTML

<section id="home" class="full-height px-lg-5">
  <div class="container">
    <div class="row">
      <div class="col-lg-10">
        <h1 class="display-4 fw-bold" data-aos="fade-up">
          {{'HOME.IMMIGRATION' | translate}}         </h1>.   <----------- this

tehcmanmax avatar Feb 07 '24 13:02 tehcmanmax

This dose not solve my issue. Error thrown is:

No provider for TranslateService!

@muhamedkarajic Did you do the import of TranslateModule in the components where you want to use the pipe?

At TS:

import {Component} from '@angular/core';
import {TranslateModule} from '@ngx-translate/core'; <----- this


@Component({
  selector: 'app-home',
  standalone: true,
  imports: [TranslateModule],
  templateUrl: './home.component.html',
  styleUrl: './home.component.scss'
})
export class HomeComponent {

}

At HTML

<section id="home" class="full-height px-lg-5">
  <div class="container">
    <div class="row">
      <div class="col-lg-10">
        <h1 class="display-4 fw-bold" data-aos="fade-up">
          {{'HOME.IMMIGRATION' | translate}}         </h1>.   <----------- this

I know how to import the module in a standalone enviroment, none of what you are saying is new to me. For me from what I understood the translation module needs to be updated to angular 17 so it supports the esmodule build functionality. Thats what I'm asking for.

muhamedkarajic avatar Feb 14 '24 10:02 muhamedkarajic

@ocombe any news man?

muhamedkarajic avatar Feb 14 '24 10:02 muhamedkarajic

There is no config specific to esmodule, it works exactly like webpack for Angular code. You can use importProvidersFrom to get the providers from ngx translate:

importProvidersFrom(TranslateModule.forRoot({
  defaultLanguage: 'en',
  loader: {
    provide: TranslateLoader,
    deps: [HttpClient],
    useFactory: HttpLoaderFactory
  }
}))

If you see an error with TranslateFakeLoader it's weird. You can just directly use the providers that the module was exporting originally, the forRoot function isn't complicated: https://github.com/ngx-translate/core/blob/master/packages/core/public-api.ts#L51-L60

ocombe avatar Feb 14 '24 10:02 ocombe

I'm curious guys to know if your configuration allows the translation in ts files through the TranslateService using instant keyword. I think it doesn't because of the async, it probably returns the key instead of the value.

MartinFerret avatar Feb 20 '24 15:02 MartinFerret

Even better, thanks!

please share the solution i am facing same issue on ngModel.

Prasanta651 avatar Feb 22 '24 10:02 Prasanta651

Hello, I'm facing the same issue and I've followed your instructions so far. Also I've tried to tinker around a bit, but with no luck....this is what I have so far

the app.config.ts file

import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideHttpClient, HttpClient, HttpBackend, HttpClientModule, withFetch } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

export const provideTranslation = () => ({
  defaultLanguage: 'en',
  loader: {
    provide: TranslateLoader,
    useFactory: HttpLoaderFactory,
    deps: [HttpBackend, HttpClient],
  },
});

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

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), 
    provideClientHydration(),
    provideAnimations(), 
    provideHttpClient(withFetch()),
    importProvidersFrom([
      HttpClientModule, 
      TranslateModule.forRoot(provideTranslation()),
      TranslateModule.forChild(provideTranslation())
    ]),]
};```

and that's the error I get when I run ng serve


```ERROR TypeError: this.http.get is not a function
    at TranslateHttpLoader.getTranslation (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/http-loader/dist/fesm2022/ngx-translate-http-loader.mjs:14:26)
    at _TranslateService.getTranslation (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:454:52)
    at _TranslateService.retrieveTranslations (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:443:81)
    at _TranslateService.setDefaultLang (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:392:24)
    at _TranslateService (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:382:12)
    at Object.TranslateService_Factory (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:708:12)
    at eval (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5239:43)
    at runInInjectorProfilerContext (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:3644:9)
    at R3Injector.hydrate (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5238:17)
    at R3Injector.get (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5106:33)
TypeError: this.http.get is not a function
    at TranslateHttpLoader.getTranslation (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/http-loader/dist/fesm2022/ngx-translate-http-loader.mjs:14:26)
    at _TranslateService.getTranslation (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:454:52)
    at _TranslateService.retrieveTranslations (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:443:81)
    at _TranslateService.setDefaultLang (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:392:24)
    at _TranslateService (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:382:12)
    at Object.TranslateService_Factory (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:708:12)
    at eval (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5239:43)
    at runInInjectorProfilerContext (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:3644:9)
    at R3Injector.hydrate (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5238:17)
    at R3Injector.get (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5106:33)
7:49:19 μ.μ. [vite] Internal server error: this.http.get is not a function
      at TranslateHttpLoader.getTranslation (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/http-loader/dist/fesm2022/ngx-translate-http-loader.mjs:14:26)
      at _TranslateService.getTranslation (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:454:52)
      at _TranslateService.retrieveTranslations (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:443:81)
      at _TranslateService.setDefaultLang (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:392:24)
      at _TranslateService (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:382:12)
      at Object.TranslateService_Factory (c:/GitProjects/BrokerAgentUI/node_modules/@ngx-translate/core/dist/fesm2022/ngx-translate-core.mjs:708:12)
      at eval (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5239:43)
      at runInInjectorProfilerContext (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:3644:9)
      at R3Injector.hydrate (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5238:17)
      at R3Injector.get (c:/GitProjects/BrokerAgentUI/node_modules/@angular/core/fesm2022/core.mjs:5106:33)```

I'm using Angular 17.2.1 with the latest version of ngx-translate and the components are stand alone. There is no app.module.ts or any usage of @NgModule

TonyStarkGR avatar Feb 27 '24 17:02 TonyStarkGR

@ocombe Will there be a provide function added in the near future so that we don't have to use importProvidersFrom?

geo242 avatar Mar 04 '24 16:03 geo242

TypeError: this.http.get is not a function at TranslateHttpLoader.getTranslation

Please remove HttpBackend from deps

jishnutv avatar Mar 10 '24 07:03 jishnutv

I used this way in my own project. (TranslateYamlHttpLoader and yaml are optional, of course.)

src\app\providers\translation.ts

import { HttpClient, HttpClientModule } from '@angular/common/http';
import { importProvidersFrom } from '@angular/core';
import { TranslateLoader, TranslateModule, TranslateModuleConfig } from '@ngx-translate/core';
import { Observable, map } from 'rxjs';
import { parse } from 'yaml';

class TranslateYamlHttpLoader implements TranslateLoader {
  constructor(
    private httpClient: HttpClient,
    public path: string = '/assets/i18n/',
  ) {}

  public getTranslation(lang: string): Observable<unknown> {
    return this.httpClient.get(`${this.path}${lang}.yaml`, { responseType: 'text' }).pipe(map((data) => parse(data)));
  }
}

const config: TranslateModuleConfig = {
  defaultLanguage: 'en',
  loader: {
    provide: TranslateLoader,
    useFactory: (httpClient: HttpClient) => new TranslateYamlHttpLoader(httpClient),
    deps: [HttpClient],
  },
};

export function provideTranslation() {
  return importProvidersFrom([HttpClientModule, TranslateModule.forRoot(config)]);
}

src\app\app.config.ts

import { provideTranslation } from './providers/translation';

export const appConfig: ApplicationConfig = {
  providers: [provideTranslation()],
};

ahmet-cetinkaya avatar Mar 18 '24 03:03 ahmet-cetinkaya

app.config.ts import { ApplicationConfig, importProvidersFrom } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideAnimations } from '@angular/platform-browser/animations'; import { HttpBackend, HttpClient, HttpClientModule, provideHttpClient } from '@angular/common/http'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateHttpLoader } from '@ngx-translate/http-loader';

export const provideTranslation = () => ({ defaultLanguage: 'en', loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient], }, });

export function HttpLoaderFactory(http: HttpClient) { return new TranslateHttpLoader(http, './assets/i18n/', '.json'); } export const appConfig: ApplicationConfig = { providers: [provideRouter(routes),provideAnimations(),provideHttpClient(),importProvidersFrom(HttpClientModule), importProvidersFrom([TranslateModule.forRoot(provideTranslation()) ]),], }; //particular components import { TranslateModule, TranslateService } from '@ngx-translate/core'; https://github.com/component({ selector: 'app-home', standalone: true, imports: [TranslateModule] }) export class HomeComponent { constructor( public translate: TranslateService ) {}

this.translate.setDefaultLang('en'); //ngonint }

// HTML Code

{{'login.title' | translate }}

shahmaulik1991 avatar Apr 22 '24 13:04 shahmaulik1991

I create a module with the command 'ng g module tranlate', there I put this code:

tranlate.module.ts:

   import { NgModule } from '@angular/core';
   import { CommonModule } from '@angular/common';
   import { HttpClient,HttpClientModule } from '@angular/common/http';
   import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
   import { TranslateHttpLoader } from '@ngx-translate/http-loader';
   
   export function HttpLoaderFactory(http: HttpClient) {
     return new TranslateHttpLoader(http,'./assets/languages/','.json');
   }
   
   @NgModule({
     declarations: [],
     imports: [
       CommonModule,
       HttpClientModule,
       TranslateModule.forRoot({
         loader: {
           provide:TranslateLoader,
           useFactory: HttpLoaderFactory,
           deps: [HttpClient]
         }
       })
     ],
     exports: [
       CommonModule,
       HttpClientModule,
       TranslateModule
     ]
   })
   export class TranlateModule { }

Once this is done, I can now import the module to different components where I use the translation, for example, this is one of my components where I use the translation.

information.component.ts:

import { Component } from '@angular/core';
import { TranlateModule } from '../../module/tranlate/tranlate.module';

@Component({
  selector: 'app-information',
  standalone: true,
  imports: [
    TranlateModule
  ],
  templateUrl: './information.component.html',
  styleUrl: './information.component.css'
})
export class InformationComponent {

}

ArmandoxxXD avatar May 04 '24 09:05 ArmandoxxXD

@siloimwald thank you very much! Your approach saves me a lot of time! It's working in 17 version!

haykeminyan avatar May 17 '24 18:05 haykeminyan

Here is how it worked for me... app.config.ts

// AoT requires an exported function for factories
export function HttpLoaderFactory(httpClient: HttpClient) {
  return  new  TranslateHttpLoader(httpClient, './assets/i18n/', '.json');
}

export const provideTranslation = () => ({
  defaultLanguage: 'en',
  loader: {
    provide: TranslateLoader,
    useFactory: HttpLoaderFactory,
    deps: [HttpClient],
  },
});

export const appConfig: ApplicationConfig = {
  providers: [
    provideAnimations(), // required animations providers
    provideHttpClient(),
    importProvidersFrom([
      HttpClientModule, 
      TranslateModule.forRoot(provideTranslation())
    ]),
    provideRouter(routes),
    
  ]
};

You deserve all the praise in the world - that worked perfectly for me!

AlineCross avatar May 21 '24 15:05 AlineCross

` // app.config import {ApplicationConfig, importProvidersFrom, provideZoneChangeDetection} from '@angular/core'; import {provideRouter} from '@angular/router';

import {routes} from './app.routes'; import {HttpClient, HttpClientModule, provideHttpClient} from "@angular/common/http"; import {TranslateHttpLoader} from '@ngx-translate/http-loader'; import {TranslateLoader, TranslateModule} from "@ngx-translate/core";

export const provideTranslation = () => ({ defaultLanguage: 'en', loader: { provide: TranslateLoader, useFactory: HttpLoaderFactory, deps: [HttpClient], }, });

export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, './assets/i18n/', '.json?' + new Date().getTime()); }

export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(), provideZoneChangeDetection({eventCoalescing: true}), importProvidersFrom([ HttpClientModule, TranslateModule.forRoot(provideTranslation()) ]), provideRouter(routes), ] }; `

` // login.component import {Component} from '@angular/core'; import {TranslateModule, TranslateService} from "@ngx-translate/core";

@Component({ selector: 'app-login', standalone: true, imports: [ TranslateModule ], templateUrl: './login.component.html', styleUrl: './login.component.scss' }) export class LoginComponent { // constructor(private translate: TranslateService) { // }

ngOnInit(): void { // this.translate.use('cn'); } }

`

brower info Error: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used withrunInInjectionContext. Find more at https://angular.dev/errors/NG0203

package.json "dependencies": { "@angular/animations": "^18.0.0", "@angular/common": "^18.0.0", "@angular/compiler": "^18.0.0", "@angular/core": "^18.0.0", "@angular/forms": "^18.0.0", "@angular/platform-browser": "^18.0.0", "@angular/platform-browser-dynamic": "^18.0.0", "@angular/router": "^18.0.0", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^8.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.14.3" }, "devDependencies": { "@angular-devkit/build-angular": "^18.0.3", "@angular/cli": "^18.0.3", "@angular/compiler-cli": "^18.0.0", "@types/jasmine": "~5.1.0", "jasmine-core": "~5.1.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", "typescript": "~5.4.2" }

maozhenhua2 avatar Jun 11 '24 16:06 maozhenhua2