Core: translate.instant('key') always yields 'key' In helper class

Created on 5 Apr 2016  路  21Comments  路  Source: ngx-translate/core

Hello everyone,

I am using the library in an ionic 2 projet.

I have initialized the TranslateService in app.ts file.

when I call {{"lessons_title" | translate}} in template I can see translated value of key 'lessons_title', but in
helper class lessonData.ts, translate.instant("lessons_title") gives the key "lessons_title" as value.

Please help.

app.ts

import {App, Platform} from 'ionic-angular';
import {TabsPage} from './pages/tabs/tabs';
import {Type} from 'angular2/core';

import {LessonsData} from './helper/lessonsData';

import {provide} from 'angular2/core';
import {Http} from 'angular2/http';
import {TranslateService, TranslateLoader, TranslateStaticLoader} from 'ng2-translate/ng2-translate';


@App({
  template: '<ion-nav [root]="rootPage"></ion-nav>',
  config: {} ,// http://ionicframework.com/docs/v2/api/config/Config/,
  providers : [
      LessonsData,
      provide(TranslateLoader, {
      useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
      deps: [Http]
    }),
    TranslateService
   ]
})


export class MyApp {
  rootPage: Type = TabsPage;

  constructor(platform: Platform, translateService : TranslateService) {

    platform.ready().then(() => {
         let userLang = navigator.language.split('-')[0];
        userLang = /(fr|en)/gi.test(userLang) ? userLang : 'fr';

        translateService.use(userLang);

    });
  }
}

lessonData.ts

import {Injectable} from "angular2/core";
import {TranslatePipe,TranslateService} from 'ng2-translate/ng2-translate';

import {Lesson} from "../modele/lesson";

@Injectable()

export class LessonsData {
    private lessons = [];

    constructor (private translate : TranslateService){
    console.log(translate); //here I can see object translate has all my data , currenLang , translations etc 
    console.log(translate.instant("lessons_title")); //gives "lessons_title" instead of "Le莽ons"

   let lesson  = new Lesson();
   lesson.number   = 1;
   lesson.title    = translate.instant("lessons_title"); 
   this.lessons.push(lesson);
    }
}

fr.json

{
"lessons_title"           : "Le莽ons"
 }

Most helpful comment

Hi ocombe,

I have found a solution by calling translate.instant("<key>") in onLangChange and it works.

But I do not know if this is the best way to do this.

import {Injectable} from "angular2/core";
import {TranslatePipe,TranslateService, LangChangeEvent} from 'ng2-translate/ng2-translate';
import {Lesson} from "../modele/lesson";

@Injectable()
export class LessonsData {
    private lessons = [];

    constructor (private translate : TranslateService){
         translate.onLangChange.subscribe((event: LangChangeEvent) => {

            let ext = ".png";

            let lesson  = new Lesson();
            lesson.number   = 1;
            lesson.title    =  translate.instant("lesson_1_title");
            lesson.titleSrc = translate.instant("lesson_1_title_src");
            lesson.desc     = translate.instant("lesson_1_desc");
            lesson.descSrc  = translate.instant("lesson_1_desc_src");
            lesson.imageSmall = "images/lessonsSmall/lesson_1_small" + ext;
            this.lessons.push(lesson);

            lesson  = new Lesson();
            lesson.number   = 2;
            lesson.title =  translate.instant("lesson_2_title");
            lesson.titleSrc = translate.instant("lesson_2_title_src");
            lesson.desc     = translate.instant("lesson_2_desc");
            lesson.descSrc  = translate.instant("lesson_2_desc_src");
            lesson.imageSmall = "images/lessonsSmall/lesson_2_small" + ext;
            this.lessons.push(lesson);

            lesson  = new Lesson();
            lesson.number   = 3;
            lesson.title =  translate.instant("lesson_3_title");
            lesson.titleSrc = translate.instant("lesson_3_title_src");
            lesson.desc     = translate.instant("lesson_3_desc");
            lesson.descSrc  = translate.instant("lesson_3_desc_src");
            lesson.imageSmall = "images/lessonsSmall/lesson_3_small" + ext;
            this.lessons.push(lesson); 
          });
    }   
}

Thanks again for your help.

All 21 comments

Hello,
translate.instant is synchronous, if your translations loader is async then you need to wait until the lang files have been loaded to get translations.
Either use translate.get which return an observable, or observe the onLangChange EventEmitter to know when it's safe to use translate.instant.

Thanks for quick reply ocombe,

I have tried to use

    translate.get("lessons_title").subscribe((result: string) => {
        lesson.title = result;
    });

but value is still same as key "lessons_title"

Could you please tell me how to get loader synchronous or observe onChangeLang ?

What's weird is that console.log(translate); display objects with all data

Does it load your file with translations correctly?
Can you give me a sample of this file?
Are you sure the key that you want is lessons_title?

Yes it load translations.

File is a simple as

{
"lessons_title"           : "Le莽ons",
"lesson_1_title"          : "Premi猫re Le莽on",
"lesson_1_title_src"      : "Erste Lektion",
"lesson_1_desc"           : "Salut, comment 莽a va ?",
"lesson_1_desc_src"       : "Hallo, wie geht鈥檚 ?",
"lesson_2_title"          : "Deuxi猫me Le莽on",
"lesson_2_title_src"      : "Zweite Lektion",
"lesson_2_desc"           : "Chez Starphone",
"lesson_2_desc_src"       : "Bei Starphone",
 }

Attached png of object translate from console
capture d ecran 2016-04-05 a 15 04 30

Yes , key lessons_title, none of the keys works.

Ok, in the providers of your @App, change this:

providers : [
    provide(TranslateLoader, {
      useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
      deps: [Http]
    }),
    TranslateService,
    LessonsData

To make sure that LessonsData uses the TranslateService that you just configured.

Done it but not better

Ok, what about:

providers : [
    provide(TranslateLoader, {
      useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
      deps: [Http]
    }),
    TranslateService,
    provide(LessonsData, {
      useFactory(translate: TranslateService) => new LessonsData(translate),
      deps: [TranslateService]
    })
]

syntax error ,
I changed to dips : [TranslateService]
but still not compiling

Ok, what if you remove "LessonsData" from the providers, and just inject it in your MyApp constructor ?

I think I need to put LessonData in the providers of apps.ts

I have tried :

This work , I get value translated in template with {{"key" | translate}}

@App({
providers : [
      provide(TranslateLoader, {
      useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
      deps: [Http]
    }),
    TranslateService,
    LessonsData
   ]
...

this , does not work, blank page

@App({
providers : [
      provide(TranslateLoader, {
      useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'),
      deps: [Http]
    }),
    TranslateService
   ]
....

Well then I give up. It's obviously not using the same instance of the translate service, but without the code to debug, it's taking too much time to guess what's wrong, sorry.

ok, thank you for you time.

I will debug and try to find what going on

Hi ocombe,

I have found a solution by calling translate.instant("<key>") in onLangChange and it works.

But I do not know if this is the best way to do this.

import {Injectable} from "angular2/core";
import {TranslatePipe,TranslateService, LangChangeEvent} from 'ng2-translate/ng2-translate';
import {Lesson} from "../modele/lesson";

@Injectable()
export class LessonsData {
    private lessons = [];

    constructor (private translate : TranslateService){
         translate.onLangChange.subscribe((event: LangChangeEvent) => {

            let ext = ".png";

            let lesson  = new Lesson();
            lesson.number   = 1;
            lesson.title    =  translate.instant("lesson_1_title");
            lesson.titleSrc = translate.instant("lesson_1_title_src");
            lesson.desc     = translate.instant("lesson_1_desc");
            lesson.descSrc  = translate.instant("lesson_1_desc_src");
            lesson.imageSmall = "images/lessonsSmall/lesson_1_small" + ext;
            this.lessons.push(lesson);

            lesson  = new Lesson();
            lesson.number   = 2;
            lesson.title =  translate.instant("lesson_2_title");
            lesson.titleSrc = translate.instant("lesson_2_title_src");
            lesson.desc     = translate.instant("lesson_2_desc");
            lesson.descSrc  = translate.instant("lesson_2_desc_src");
            lesson.imageSmall = "images/lessonsSmall/lesson_2_small" + ext;
            this.lessons.push(lesson);

            lesson  = new Lesson();
            lesson.number   = 3;
            lesson.title =  translate.instant("lesson_3_title");
            lesson.titleSrc = translate.instant("lesson_3_title_src");
            lesson.desc     = translate.instant("lesson_3_desc");
            lesson.descSrc  = translate.instant("lesson_3_desc_src");
            lesson.imageSmall = "images/lessonsSmall/lesson_3_small" + ext;
            this.lessons.push(lesson); 
          });
    }   
}

Thanks again for your help.

Ok nice :)

hi all,
I need to get the translations done based on the browser language.The translations are placed in the js file as key value pairs.Like for example: language_en.js file
{
"key":"globalWelcomeLabel",
"value":"Welcome",
"description":"Welcome label"
},
and for language_de.js
{
"key":"globalWelcomeLabel",
"value":"Welkom",
"description":"Welcome label"
},

I have added the angular-translate.js and also angular-translate-loader-static-files.js in index.html
in app.js , added 'pascalprecht.translate' in app.module and $translateProvider in .config
and the implementation of $translateProvider as

$translateProvider.useStaticFilesLoader({
prefix: '/translations/language_en',
suffix: '.js'
})
.preferredLanguage('en');
$translateProvider.useSanitizeValueStrategy(null);

now how do i get the value from the key in an alert .tried with translate.instant('welcomeMessage') but it gives me the same data instead of giving the value welcome /welkom ,in this case welcome as the file loaded is language_en

On your app.components.ts inject private translate: TranslateService in the constructor (of course you have to import it before), then still inside the constructor set the language according to the browser/navigator language (in this case if the language is not Portuguese, Germany, Spanish or English it will use English):

var lang = this.translate.getBrowserLang();
lang = /(pt|de|en|es)/gi.test(lang) ? lang : 'en';
this.translate.setDefaultLang('en');
this.translate.use(lang);

its too late to answer this, but it will be usefull for anyone facing same probelm.
your first code @debgoume is 100% correct but you are missing one thing you are putting the translate code inside the platform ready event, so your translate config will not be available until the platform is ready. the solution is just put the config translate code outside the platform ready function.

this.translate.get(this.pageTitle).subscribe((text:string) => {
this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
title.setTitle(this.translate.instant(text))
});
});

If I can answer for other people who will search a solution: In your app.component or the component where you initialize the app

ngOnInit() { this.translate.use('fr' | 'en').subscribe(() => { // your initilization things } }

because you have to load all translations to do an instant call on your translate service

I faced same issue.
The issue is need to set default language
translate.setDefaultLang('en');
Before
translate.instant(TOKEN);

FInaly resoved it by this way. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

madoublet picture madoublet  路  3Comments

chris31389 picture chris31389  路  3Comments

pndewit picture pndewit  路  3Comments

bjornharvold picture bjornharvold  路  3Comments

crebuh picture crebuh  路  3Comments