I'm submitting a ... (check one with "x")
[ ] bug report => check the FAQ and search github for a similar issue or PR before submitting
[x] support request => check the FAQ and search github for a similar issue before submitting
[ ] feature request
My use case is that I need the web site localized in all of the supported languages, but I also need part of an app (invoice editor) to be localized in different locale, depending what language the invoice is made with. (Think US based worker, that speaks french and is using the app in french, but she is sending an invoice to someone in Spain, and wants to preview the invoice in Spanish.) In this case, there area actually multiple selected locales at the same time in play: the ui should be in french, but the are containing the invoice preview should display spanish.
Any ideas how to tackle this one? Can I have multiple instances of TranslateService? We're using AOT.
Yeah, I got the same problem.
I ended up doing it like this:
import { Pipe, Injectable, Inject, ChangeDetectorRef } from '@angular/core'
import { Http } from '@angular/http'
import { TranslatePipe } from '@ngx-translate/core'
import { TranslateService, TranslateDefaultParser, MissingTranslationHandler, MissingTranslationHandlerParams } from '@ngx-translate/core'
import { TranslateHttpLoader } from '@ngx-translate/http-loader'
@Injectable()
@Pipe({
name: 'translatecustom',
pure: false // required to update the value when the promise is resolved
})
export class TranslateCustomPipe extends TranslatePipe {
constructor(@Inject('customTranslator') private customTranslator: CustomTranslationService, private _theRef: ChangeDetectorRef) {
super(customTranslator, _theRef)
}
}
@Injectable()
export class CustomTranslationService extends TranslateService {
constructor(http: Http) {
super(null, new TranslateHttpLoader(http, '/assets/i18n/custom.', '.json'), new TranslateDefaultParser(), new MyMissingTranslationHandler(), true)
}
}
export class MyMissingTranslationHandler implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams) {
let key = params ? params.key : 'no key!'
if (console) {
console.log('Custom translation missing for ' + key)
}
return 'Custom translation missing for ' + key
}
}
Notice the /assets/i18n/custom. part, that configures the loader to read from /assets/i18n/custom.en.json for an example.
And in your app module:
@NgModule({
declarations: [
...,
TranslateCustomPipe
],
providers: [
CustomTranslationService,
{ provide: 'customTranslator', useExisting: CustomTranslationService }
]
})
...
After this you can {{ 'translationkey' | translatecustom }} in your component, and inject CustomTranslationService to your components to use different language etc.
Note that you need to adapt this solution if you use different loader + the usual ymmv and code is provided as is and may contain bugs etc.
It would be EXTREMELY nice to see proper support for multiple TranslationServices and the option to specify which one is used in pipe / directive etc. Think of named services, where the current is default and used if nothing is specified.
The solution given here may break in future releases.
Good Idea.
Nice. Works as intended
Is there any update on this? Is this still the way to do it in late 2019?
@swftvsn Do you have a running example project?
Thank you!
I also used in my case the approach proposed by @swftvsn, however for the CustomTranslationService example is a bit outdated and the constructor is expecting now some more parameters. I ended up with something like:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { TranslateService, TranslateDefaultParser, FakeMissingTranslationHandler, TranslateFakeCompiler } from '@ngx-translate/core'
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
@Injectable()
export class CustomTranslationService extends TranslateService {
constructor(http: HttpClient) {
super(null, new TranslateHttpLoader(http, 'assets/i18n/', '.json'), new TranslateFakeCompiler(), new TranslateDefaultParser(), new FakeMissingTranslationHandler(), false, true, false, null)
}
}
The last parameter is for the default language, which I however don't know upfront. Later you can then just call CustomTranslationService.use(lang) and use the service like you are used to. Of course the loader, compiler etc can be replaced as well with custom ones. Maybe this update saves somebody some time :man_shrugging:
Most helpful comment
I ended up doing it like this:
Notice the /assets/i18n/custom. part, that configures the loader to read from /assets/i18n/custom.en.json for an example.
And in your app module:
After this you can
{{ 'translationkey' | translatecustom }}in your component, and injectCustomTranslationServiceto your components to use different language etc.Note that you need to adapt this solution if you use different loader + the usual ymmv and code is provided as is and may contain bugs etc.
It would be EXTREMELY nice to see proper support for multiple TranslationServices and the option to specify which one is used in pipe / directive etc. Think of named services, where the current is default and used if nothing is specified.
The solution given here may break in future releases.