hi everyone, i hava. a problem, i can't get the translation in the scope 'countries'
the default language is 'it' so should get countries/it.json right?
i use nx
i tried also with inject theproviders: [
{
provide: TRANSLOCO_SCOPE,
useValue: 'countries',
},
],
inside the component and use the translate method but don't work 😕
getTranslation
uses an http request and not just import the files and return them as :import de from '@assets/i18n/de.json'
import en from '@assets/i18n/en.json'
export class TranslocoHttpLoader implements TranslocoLoader {
constructor() {}
getTranslation(lang: string): Observable<Translation> {
return lang === 'de' ? of(de) : of(en)
}
}
getScopeAndLangFromFullPath.js
filePath: /home/agent/_work/4/s/apps/frontend/src/assets/i18n/ar.json
translationPath: /home/agent/_work/4/s/apps/frontend/src/assets/i18n
Hello. I'm having trouble loading lang files in a nested component hosted in lazy module. For some reason it only loads on the second time the component is initialized. Repo here... https://github.com/vdiaz1130/transloco-nx
Appreciate the help.
if (isLocaleFormat(val)) {
return val;
}
Hey there Transloco-Team,
we got an Angular-App with an integrated login process (login without translation). We added Transloco's RootModule in our AppModule (like described here) without a default language (because we want the persisted user language to be the default one) -> so Transloco is bootstrapping with his default language 'en'. Additionally after a succesfull login we load the persisted user language from our backend server like described in your recipe "Prefetch the User Language" with the TranslocoService.
thanks in advance!
APP_INITIALIZER
.TranslocoRootModule
per application.Hi
can someone help how to do the unit testing while using transoloco.translate() in typescript?
https://ngneat.github.io/transloco/docs/unit-testing this works while using pipe/directive on html dom.
When I have a utility function like below in my service.:
public getFormattedCapacity(val: number): string {
let result: string = "";
if (typeof val == 'number') {
if (val >= this.TBYTE) {
result = (val / this.TBYTE).toFixed(2) + " " + this.transloco.translate('terabyte');
} else if (val >= this.GBYTE) {
result = (val / this.GBYTE).toFixed(2) + " " + this.transloco.translate('gigabyte');
} else if (val >= this.MBYTE) {
result = (val / this.MBYTE).toFixed(2) + " " + this.transloco.translate('megabyte');
} else if (val >= this.KBYTE) {
result = (val / this.KBYTE).toFixed(2) + " " + this.transloco.translate('kilobyte');
} else if (val >= 0) {
result = val + " " + this.transloco.translate('byte');
} else {
result = this.transloco.translate('notapplicable');
}
}
return result;
}
}
when im writing unit testing:
it("Should return capacity in terms of KB when call method getFormattedCapacity", () => {
let value = service.getFormattedCapacity(1024);
expect(value).toBe("1.00 kilobyte"); // asserting to true. I mean returning key but not value
expect(value).toBe("1.00 KB"); //Intension/expected assertion behavior
});
Here is the beforeeach looks:
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
SharedModule,
TranslocoTestingModule,
getTranslocoModule()
],
providers: [MyUtilService,
GlobalService,
TranslocoService
]
});
service = TestBed.inject(MyUtilService);
}));
@shravansofts
The Translate function does not wait for the translations to load. You have to preload them. You can check out the TranslocoPreloadLangsModule
, or you can just setActiveLang
in your beforeEach
and wait for it to actually load. When possible, try to use selectTranslate
instead, since it will produce an observable that changes every time the translations are loaded.
We had a similar situation before, I've quoted the previous thread below.
@avifox spectator is not necessary, but it really makes everything easier. My examples are below.
For missing keys, I agree with @shaharkazaz , if you want to check for missing keys, just runtransloco-keys-manager find
and look for the missing and unused keys. If you wanted it automated, maybe there is a way to parse the output and make it a pass/fail step in your build process.i pulled out my setLanguage promise into a function that i can call:
/** setting the language does not happen immediately. It must first load, * then change detection must fire. * This method will set the lang, and wait for it to load and detect changes. */ async function setLang(lang: string) { await new Promise(resolve => { translocoService.events$.pipe( filter((t: TranslocoEvents) => t.type === 'translationLoadSuccess') ).subscribe(t => resolve()); translocoService.setActiveLang(lang); }).then(() => spectator.detectChanges()); }
here is my beforeEach:
beforeEach(() => { // tests were written for the case that spanish is the default language TranslocoConfigProvider.useValue.defaultLang = 'es'; spectator = createSpectator(); translocoService = spectator.inject(TranslocoService); // set lang here so we can make sure it is loaded before running tests setLang('es'); });
make sure to also use the
TranslocoTestingModule
, here's what I used, borrowed from Transloco:export const languageMap = { en, es, 'i18nTest/en': admin, 'i18nTest/es': adminSpanish, 'lazyPage/en': lazy, 'lazyPage/es': lazySpanish, 'mf/en': transpilersMessageFormat, 'mf/es': transpilersMessageFormatSpanish }; export function getTranslocoTestModule(config: Partial<TranslocoConfig> = {}) { return TranslocoTestingModule.withLangs( languageMap, { availableLangs: ['es', 'en'], defaultLang: 'es', fallbackLang: 'en', ...config } ); }
@shravansofts @brian
The reason this is working for you while using the directive or pipe is that we take of it behind the scenes, when you use the service it's your responsibility.
This behavior doesn't make sense while testing, that's why in v2.20.0 we introduced the preloadLangs
property in the testing module config, which tells transloco to preload the languages into the service.
I updated the docs with the property since it was missing and this question was raised several times, even recently: ngneat/transloco#400.
There is more information regarding this change here.
Hello, can you provide a usage example of the upcase customFormatter. https://www.npmjs.com/package/@ngneat/transloco-messageformat
I tried the example but nothing I've used in the JSON file works: {{itemName | upcase}}, {{itemName, upcase}}, {itemName | upcase}, {itemName, upcase}. I also reversed them (e.g {{upcase itemName}})
{ provide: LOCALE_CURRENCY_MAPPING, useValue: {} },
{ provide: LOCALE_LANG_MAPPING, useValue: {} },
{ provide: LOCALE_DEFAULT_LOCALE, useValue: 'en-US' },
{ provide: LOCALE_CONFIG, useValue: {} },
{ provide: TRANSLOCO_NUMBER_TRANSFORMER, useValue: {} },
{ provide: TRANSLOCO_DATE_TRANSFORMER, useValue: {} }
Recently, I noticed that my tests started complaining about missing providers for various constants from TranslocoLocale. Is there something different I need to start doing in my unit tests? For now, I have to provide each one of these for the tests to pass.
{ provide: LOCALE_CURRENCY_MAPPING, useValue: {} }, { provide: LOCALE_LANG_MAPPING, useValue: {} }, { provide: LOCALE_DEFAULT_LOCALE, useValue: 'en-US' }, { provide: LOCALE_CONFIG, useValue: {} }, { provide: TRANSLOCO_NUMBER_TRANSFORMER, useValue: {} }, { provide: TRANSLOCO_DATE_TRANSFORMER, useValue: {} }
What exactly are you testing? it seems redundant to fake all these providers in unit tests ( usually you need to fake just what you are using e.g. pipe, directive, etc... ). I suggest you take a look at spectator as a good practice library for testing, there are many use-cases there that might suit your need.
Hello, is there a way to use a scope with the translation API ?
I would like to do something like that inside a lazy route component using the scope "product".
transloco.translate('product.step.optional');
The code tries to load it from the root i18n file instead of "product" scope
I also tried:
transloco.translate('step.optional', {}, 'product');
Which extract in the right file, but doesn't use the scope for translation
I'm having trouble testing anything that uses TranslocoLocale pipes in a service.
TranslocoLocale pipes in my component templates work correctly in unit tests, but if I inject the pipes in a service, injected in the constructor, they do not work. How should I setup my tests for this?
In the example below, My service uses the TranslocoDecimalPipe. In my test I get the error:
NullInjectorError: StaticInjectorError(DynamicTestModule)[L10nTestService -> TranslocoDecimalPipe]:
StaticInjectorError(Platform: core)[L10nTestService -> TranslocoDecimalPipe]:
NullInjectorError: No provider for TranslocoDecimalPipe!
import { Injectable } from '@angular/core';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { TranslocoModule } from '@ngneat/transloco';
import { TranslocoDecimalPipe, TranslocoLocaleModule } from '@ngneat/transloco-locale';
@Injectable({ providedIn: 'root' })
class L10nTestService {
decimalValue: string;
constructor(private translocoDecimalPipe: TranslocoDecimalPipe) {
this.decimalValue = translocoDecimalPipe.transform(1234567890.123456);
}
}
describe('L10ntestService', () => {
let spectator: SpectatorService<L10nTestService>;
const createService = createServiceFactory<L10nTestService>({
service: L10nTestService,
imports: [
TranslocoModule,
TranslocoLocaleModule.init()
]
});
beforeEach(() => spectator = createService());
it('decimal value should be transformed', () => {
expect(spectator.service.decimalValue).toBe('1,234,567,890.123');
});
});