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

How to implement multiple languages in one page #570

Open
swftvsn opened this issue Jun 16, 2017 · 6 comments
Open

How to implement multiple languages in one page #570

swftvsn opened this issue Jun 16, 2017 · 6 comments

Comments

@swftvsn
Copy link

swftvsn commented Jun 16, 2017

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.

@webcrack4
Copy link

Yeah, I got the same problem.

@swftvsn
Copy link
Author

swftvsn commented Jun 22, 2017

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.

@webcrack4
Copy link

Good Idea.

@momegas
Copy link

momegas commented May 9, 2018

Nice. Works as intended

@mrvonwyl
Copy link

mrvonwyl commented Oct 17, 2019

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!

@gasfab999
Copy link

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 🤷‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants