我正在为我的Angular 2应用程序做一个i18n服务系统 . 为了避免不纯的管道,我向翻译管道添加了一个额外的参数,该更改将触发管道值更新,因此它将更新翻译的文本 .

什么是最佳做法: Raise an event from the service and subscribe in each component to detect the language change

VS

Set the service variable lang as public and add to it to the pipe as parameter?

我已经测试过并且两者都有效 .

Using Event emitter:

component.html

<button md-button class="btn-register">{{'Register' | _:lang}}</button>

component.ts

export class LoginComponent implements OnInit {
    loginForm: FormGroup;
    public lang: string;
    onLangChange: EventEmitter<LangChangeEvent>;

    constructor(private _fb: FormBuilder, private _authService: AuthService, private tr:TranslateService) {

    }

    ngOnInit():any {

        //monitor language change
        this.onLangChange = this.tr.onLangChange.subscribe( (event: LangChangeEvent) => {
            this.lang = event.lang;
        });

        this.loginForm = this._fb.group({
            email: ['', Validators.required],
            password: ['', Validators.compose( [Validators.required, hasNumbers] ) ]
        });

    }

    onSubmit(form) {
        this._authService.login( this.loginForm.value );
    }
}

translate.service.ts

import {Injectable, EventEmitter} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {Languages} from "../config/Constants";

export interface LangChangeEvent {
    lang: string;
}

@Injectable()
export class TranslateService {

    public lang: string;
    dictionary: any = {};

    /**
     * An EventEmitter to listen to lang change events
     * onLangChange.subscribe((params: LangChangeEvent) => {
     *     // do something
     * });
     * @type {ng.EventEmitter<LangChangeEvent>}
     */
    public onLangChange: EventEmitter<LangChangeEvent> = new EventEmitter<LangChangeEvent>();

    constructor(private http: Http, private path:string) {

        let lang = this.detectLang();
        this.setLanguage(lang);
    }

    /**
     * A standard alias used for the translate function
     * @param val
     * @returns {string}
     * @private
     */
    public _(val: string) {
        return this.dictionary[val] ? this.dictionary[val] : val;
    }

    public setLanguage(lang: string) {

        if(Languages[lang]) {
            this.loadLanguage(lang, Languages[lang].path);
        }
    }

    private loadLanguage(lang:string, url: string) {
        return this.http.get(url).toPromise()
            .then( dictionary =>
            {
                this.dictionary = dictionary.json();
                this.lang = lang;
                this.onLangChange.emit({ lang: this.lang });
            })
            .catch( error => console.log(error) );
    }

    private detectLang(): string {
        if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
            return 'en';
        }
        let browserLang: any;
        if (typeof window.navigator['languages'] !== 'undefined' && window.navigator['languages'].length > 0) {
            browserLang = window.navigator['languages'][0].indexOf('-') !== -1 || window.navigator['languages'].length < 2 ? window.navigator['languages'][0] : window.navigator['languages'][1];
        } else {
            browserLang = window.navigator['language'] || window.navigator['browserLanguage'];
        }

        return browserLang && browserLang.length ? browserLang.split('-')[0] : 'en'; // use navigator lang if available
    }
}

Using a public variable:

<button md-button class="btn-register">{{'Register' | _:tr.lang}}</button>

component.ts

export class LoginComponent implements OnInit {
    loginForm: FormGroup;

    constructor(private _fb: FormBuilder, private _authService: AuthService, private tr:TranslateService) {

    }

    ngOnInit():any {

        this.loginForm = this._fb.group({
            email: ['', Validators.required],
            password: ['', Validators.compose( [Validators.required, hasNumbers] ) ]
        });

    }

    onSubmit(form) {
        this._authService.login( this.loginForm.value );
    }
}

translate.service.ts

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {Languages} from "../config/Constants";

export interface LangChangeEvent {
    lang: string;
}

@Injectable()
export class TranslateService {

    public lang: string;
    dictionary: any = {};


    constructor(private http: Http, private path:string) {

        let lang = this.detectLang();
        this.setLanguage(lang);
    }

    /**
     * A standard alias used for the translate function
     * @param val
     * @returns {string}
     * @private
     */
    public _(val: string) {
        return this.dictionary[val] ? this.dictionary[val] : val;
    }

    public setLanguage(lang: string) {

        if(Languages[lang]) {
            this.loadLanguage(lang, Languages[lang].path);
        }
    }

    private loadLanguage(lang:string, url: string) {
        return this.http.get(url).toPromise()
            .then( dictionary =>
            {
                this.dictionary = dictionary.json();
                this.lang = lang;
            })
            .catch( error => console.log(error) );
    }

    private detectLang(): string {
        if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
            return 'en';
        }
        let browserLang: any;
        if (typeof window.navigator['languages'] !== 'undefined' && window.navigator['languages'].length > 0) {
            browserLang = window.navigator['languages'][0].indexOf('-') !== -1 || window.navigator['languages'].length < 2 ? window.navigator['languages'][0] : window.navigator['languages'][1];
        } else {
            browserLang = window.navigator['language'] || window.navigator['browserLanguage'];
        }

        return browserLang && browserLang.length ? browserLang.split('-')[0] : 'en'; // use navigator lang if available
    }
}