Easy and clean way to do it
If you're looking to change the language of the entire application when changing a language without having to reload the page, I would consider taking a look at the following https://github.com/ngx-translate/core.
ngx-translate let you use pipe to translate languages, when you do change the language inside the ngx translate service, then every pipe do upload themselves and your app do change their languages, without any other fuss
<h2>{{ 'WELCOME' | translate }}</h2>
import { TranslateService } from '@ngx-translate/core'
//..,
constructor(private _translateService: TranslateService){}
setLanguage(language: string) {
this._translateService.use(language)
}
And you're done, I let you read this for further details.
Response to the question
This is my own way of doing things if I didn't had the right to use ngx-translate. I would create a "base" file, with the logic you need, we'll talking here about observable I think
let's name it base.component.ts
import { Directive, OnDestroy, OnInit } from '@angular/core'
import { Subject } from 'rxjs'
import { filter, takeUntil } from 'rxjs/operators'
import { LanguageService } from 'some/where'
@Directive()
export class BaseComponent implements OnInit, OnDestroy {
protected _unsubscribeAll: Subject<any> = new Subject()
constructor(public languageService: LanguageService) {}
ngOnInit(): void {
this.languageService.onLanguageChanged$
.pipe(
filter((langChange) => (langChange?.firstChange ? false : true)), // Avoid subscribing to the first change
takeUntil(this._unsubscribeAll),
)
.subscribe((value) => {
// Do the reload you need to
})
this._extendedInit()
}
protected _extendedInit() {
// For your default ngOnInit
}
ngOnDestroy(): void {
this._unsubscribeAll.next()
this._unsubscribeAll.complete()
this._extendedDestroy()
}
protected _extendedDestroy() {
// For your default ngOnDestroy
}
}
You then, extends every component that need to be updated on language change, (or anything else, if you need to)
import { Directive } from '@angular/core'
import { LanguageService } from 'some/where'
import { BaseComponent } from 'some/where'
@Directive()
export class RandomComponent extends BaseComponent {
constructor(public languageService: LanguageService) {
super(languageService)
}
protected _extendedInit(): void {
// For custom ngOnInit
}
}
If you do not need to add other import to the constructor, you may ignore it, like the following
import { Directive } from '@angular/core'
@Directive()
export class RandomComponent extends BaseComponent {
protected _extendedInit(): void {
// For custom ngOnInit
}
}
And if needed, this his how you could create your service.
I did add the same logic as angular do for the ngOnChange, maybe help you avoid reloading things if you do not want to, for example for the first load
import { Injectable } from '@angular/core'
import { BehaviorSubject } from 'rxjs'
export interface LangChange {
previousValue: any
currentValue: any
firstChange: boolean
}
@Injectable({
providedIn: 'root',
})
export class LanguageService {
onSelectedLanguageChange$: BehaviorSubject<LangChange> = new BehaviorSubject(null)
constructor() {}
setLanguage(language: string) {
this.onSelectedLanguageChange$.next({
previousValue: this.onSelectedLanguageChange$.value,
currentValue: language,
firstChange: !this.onSelectedLanguageChange$.value,
})
}
}
then, into your app.component
or anywhere you wants
constructor(private _languageService: LanguageService) {}
changeLang(language: string) {
this._languageService.setLanguage('de')
}