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

Support for Angular v17 #1460

Open
kgish opened this issue Dec 1, 2023 · 32 comments
Open

Support for Angular v17 #1460

kgish opened this issue Dec 1, 2023 · 32 comments

Comments

@kgish
Copy link

kgish commented Dec 1, 2023

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.

@ocombe
Copy link
Member

ocombe commented Dec 1, 2023

What do you mean ngModule is no longer used?

@siloimwald
Copy link

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.

@ahmedalmorsy1993
Copy link

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

@kgish
Copy link
Author

kgish commented Dec 3, 2023

Thanks, now working!

@ahmedalmorsy1993
Copy link

Thanks, now working!

should I update my project now to work with me?

@eskwisit
Copy link

eskwisit commented Dec 3, 2023

@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],
  },
});

@kgish
Copy link
Author

kgish commented Dec 4, 2023

Even better, thanks!

@kgish
Copy link
Author

kgish commented Dec 14, 2023

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

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

@gultyayev
Copy link

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

@ShailaPatilacmeconnect
Copy link

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

@hpardess
Copy link

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),
    
  ]
};

@muhamedkarajic
Copy link

muhamedkarajic commented Jan 18, 2024

I get following issue:

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

image

@muhamedkarajic
Copy link

muhamedkarajic commented Jan 18, 2024

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
Copy link

Any news on this?

@tehcmanmax
Copy link

tehcmanmax commented Feb 7, 2024

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

@muhamedkarajic
Copy link

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
Copy link

@ocombe any news man?

@ocombe
Copy link
Member

ocombe commented Feb 14, 2024

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

@MartinFerret
Copy link

MartinFerret commented Feb 20, 2024

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.

@Prasanta651
Copy link

Prasanta651 commented Feb 22, 2024

Even better, thanks!

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

@TonyStarkGR
Copy link

TonyStarkGR commented Feb 27, 2024

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

@geo242
Copy link

geo242 commented Mar 4, 2024

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

@jishnutv
Copy link

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

Please remove HttpBackend from deps

@ahmet-cetinkaya
Copy link

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()],
};

@shahmaulik1991
Copy link

shahmaulik1991 commented Apr 22, 2024

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 }}

@ArmandoxxXD
Copy link

ArmandoxxXD commented May 4, 2024

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 {

}

@haykeminyan
Copy link

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

@AlineCross
Copy link

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!

@maozhenhua2
Copy link

`
// 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" }

@MarikaKonturova
Copy link

MarikaKonturova commented Jun 25, 2024

it is quite similar to what worked for me in angular 18 (^18.0.4). i think you can use it in v17 as well #1481

@yl-endress
Copy link

+1

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