core: Cannot use with Angular AOT Compiler

I’m submitting a … [x] bug report

Current behavior Compiling an application with the angular AOT compiler fails, when ng2-translate is included in the module. The following import leads to an error:

...
imports: [TranslateModule.forRoot()]
...
Error: Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function

Expected/desired behavior It should compile successfully.

Please tell us about your environment:

  • ng2-translate version: 2.4.1
  • Angular version: 2.0.0-rc.X 2.0.0-rc.5
  • Language: TypeScript 2.0.0

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 9
  • Comments: 52 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Actually @SamVerschueren, if @ocombe could take a look to that problem that would be much great. If I understand correctly that there is no solution to use ng2-translate with AoT, all people who migrated to Ionic 2 RC since yesterday and who are using ng2-translate are blocked because of that issue 😦

Hello, thanks for the report ! I haven’t had the chance to use the AoT compiler because it was not working on windows… it does now with rc6 so I will try and fix this

@peterpeterparker I understand that it might be urgent for some people. But you must know that @ocombe is doing this in his spare time, like most of the open source contributors. If you want this so badly, nothing stops you from contributing and doing a decent PR yourself. Open source is not the same as consultancy for free. And that’s what I meant with my comment. @ocombe should solve this when he finds the time to solve it or someone else should jump in and help him out.

Alright, after fiddling around with this I think the issue is that we don’t have a metadata.json file which seems to be required for AOT. Basically this means that the library should be compiled with ngc as well. I tried doing that and I got a metadata.json file, but it didn’t work yet entirely.


Extra notes.

When using the master branch (don’t see any improvement with the npm package though), I managed to get another error.

Error: Unexpected value ‘TranslateModule’ exported by the module ‘SharedModule’

And Google shows me that it has something to do with the metadata file.

What was I doing wrong in the first place? If you provide a loader yourself, (1) make sure it uses a function as well and (2), it is exported.

// The `export` seems to be an important piece of the puzzle
export function translateLoaderFactory(http: any) {
    return new TranslateStaticLoader(http, 'app/shared/i18n', '.json');
}

@NgModule({
    imports: [
        TranslateModule.forRoot({
            provide: TranslateLoader,
            useFactory: translateLoaderFactory,
            deps: [Http]
        })
    ]
})
export class AppModule { }

This only helped with the code in master, not the one on npm. Not sure if you made any changes since the latest release?

It works like a charm with the exported function, thanks you very much guys! 😃

@TdyP I think it is a bug but you can workaround it by defining translateLoaderFactory. This worked for me:

import {TranslateModule, TranslateStaticLoader} from "ng2-translate/ng2-translate";
import {TranslateLoader} from "ng2-translate";

export function translateLoaderFactory(http: any) {
  return new TranslateStaticLoader(http, './assets/i18n', '.json');
}
@NgModule({
imports: [
    IonicModule.forRoot(MyApp),
    HttpModule,
    TranslateModule.forRoot({
    provide: TranslateLoader,
       useFactory: translateLoaderFactory,
       deps: [Http]
   }),

If you change ‘./assets/i18n’ to ‘./i18n’ you should get the default behaviour I guess.

The just pulled version (3.0.0) fix AoT problem for me 🎉

I got it working last night. I am using it in an Ionic 2 RC0 project, so i don’t know if it will work for everybody.

1 I build the plugin using the steps described in this article by @isaacplmann

2 I copied the over the newly generated files over the original files from the NPM repo in my project

3 I added the following to the to the /node_modules/@ionic/app-scripts/config/rollup.config.js

commonjs({
        namedExports: {
            'node_modules/ng2-translate/ng2-translate.js': [ 'TranslatePipe', 'TranslateLoader', 'TranslateStaticLoader', 'TranslateService' ]
        }
    })

This was the suggestion of peelfresh on the ionic forum

4 I added the following code to the @ngModule:

 export function translateLoaderFactory(http: any) {
    return new TranslateStaticLoader(http, 'assets/i18n', '.json');
}

import section:

TranslateModule.forRoot(
        {
            provide: TranslateLoader,
            useFactory: translateLoaderFactory,
            deps: [Http]
        }
    )

5 For the import statements i used:

import {TranslateModule} from "ng2-translate/ng2-translate";
import {TranslateService, TranslateLoader, TranslateStaticLoader} from "ng2-translate/src/translate.service";

I hope this makes sense, because it was a very long day yesterday to get it sort of working

Not yet, I was too busy with angular connect 😦 I’ll do it this week end !

Wow thanks for the hard work @SamVerschueren Having to compile all external libs to make them compatible with AoT seems like a really bad design in my opinion, there’s no way every lib author knows that he has to do that, and it means that if you want to do AoT you cannot use an external lib that isn’t AoT compatible…

I think it’s time to call the A-Team to get a real idea of what’s going on: @robwormald @vicb @mhevery @alexeagle @vsavkin any idea on this? How can we make an external lib work with the AoT compiler? Are we on the wrong path here, or should the lib really be pre compiled before distribution?

@krizroring this solution works fine in browser but if you try build a platform app, the compilation fails. In my app I use only two languages and I made a easy workaround : I created a @Pipe with same name of @ocombe lib where I use a JSON file like a static var. In the future I will have to change the include lib with the new release without modify the html template

I wrote up an article with steps to add *.metadata.json files to your library. I agree that documentation is lacking, and most library authors have no idea this is required.

Ok I’ve got the confirmation from @brandonroberts that if we want the library to be AoT compatible, it should be pre compiled and the metadata files published on npm, I’ll work on that and try to make a working release Here is an example of a lib with AoT: https://github.com/brandonroberts/aot-library/tree/aot And the app using the lib: https://github.com/brandonroberts/aot-app/tree/aot

If you use /assets/i18n it will try to load the language files from the root of your app space. You have to put a dot in the beginning or ommit the slash to loads it from the correct place. So you have to use

export function translateLoaderFactory(http: any) {
    return new TranslateStaticLoader(http, './assets/i18n', '.json');
}

if your language files are stored in src/assets/i18n folder.

Maybe this should have been added to the README.

that’s why I wrote “would be much great”

It works, thanks. Figured out there were another lambda function within the app.module.ts

I did not mean it offensive or something don’t get me wrong 😄

@apreg coolio 😃 as I say, just wrote it down in case someone face the same issue as I did.

Here it’s working fine with 3.0.0 and Ionic 2 rc 0 😃

@apreg You’re right! @TdyP It’s not a bug from ng2-translate it self, and it’s not a bug anymore. Angular 2 need to have reference to this function when compiling it. See here (https://github.com/angular/angular/issues/10789#issuecomment-242220591)

I’m still having issues to get this working in Ionic 2 RC.0. I’ve started over from a fresh app to try to figure it out, but no success. I’m using ng2-translate v3.0.0.

Here’s my app.module.ts :

import {BrowserModule} from "@angular/platform-browser";
import { NgModule } from '@angular/core';
import {HttpModule} from '@angular/http';
import { IonicApp, IonicModule } from 'ionic-angular';
import {TranslateModule} from 'ng2-translate/ng2-translate';
import { MyApp } from './app.component';
import { AboutPage } from '../pages/about/about';
import { ContactPage } from '../pages/contact/contact';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';

@NgModule({
  declarations: [
    MyApp,
    AboutPage,
    ContactPage,
    HomePage,
    TabsPage
  ],
  imports: [
    IonicModule.forRoot(MyApp),
    BrowserModule,
    HttpModule,
    TranslateModule.forRoot()
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    AboutPage,
    ContactPage,
    HomePage,
    TabsPage
  ],
  providers: []
})
export class AppModule {}

app.component.ts:

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from 'ionic-native';
import {TranslateService} from 'ng2-translate/ng2-translate';

import { TabsPage } from '../pages/tabs/tabs';


@Component({
  template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
  rootPage = TabsPage;

  constructor(platform: Platform, translate: TranslateService) {
    // this language will be used as a fallback when a translation isn't found in the current language
    translate.setDefaultLang('en');

     // the lang to use, if the lang isn't available, it will use the current loader to get them
    translate.use('en');

    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault();
    });
  }
}

I’m not using ng2-translate anywhere else in my code at the moment.

Here’s the error I have at compilation (ionic run android):

[12:22:26]  ngc error: Error: Error at /media/data/dev/myApp/.tmp/app/app.module.ngfactory.ts:96:27: Cannot find module '../../src/translate.service'.
Error at /media/data/dev/myApp/.tmp/app/app.module.ngfactory.ts:397:94: Property 'translateLoaderFactory' does not exist on type 'typeof "/media/data/dev/myApp/.tmp/app/app.module"'.
    at check (/media/data/dev/myApp/node_modules/@angular/tsc-wrapped/src/tsc.js:31:15)
    at Tsc.typeCheck (/media/data/dev/myApp/node_modules/@angular/tsc-wrapped/src/tsc.js:86:9)
    at /media/data/dev/myApp/node_modules/@angular/tsc-wrapped/src/main.js:33:23
    at process._tickCallback (internal/process/next_tick.js:103:7)
    at Function.Module.runMain (module.js:577:11)
    at startup (node.js:160:18)
    at node.js:456:3

I don’t see what I’m missing. Any Ionic user who could help me out?

Thanks guys!

No hurry @ocombe. Take a look whenever you find the time!