import { Http } from '@angular/http'; import { ModuleWithProviders, NgModule, Inject, Injectable, Directive, ElementRef, HostListener, Input, Renderer } from '@angular/core'; declare var navigator:any; // Use as reference: https://github.com/ngx-translate/core/tree/master/src @Injectable() export class LocaleService { get URL_TPL() {return 'src/lang/messages-{0}.json'}; private _currentLang : string = null; private _messages : any = null; private _elements = new Array(); private constructor(private http: Http, @Inject('INITIAL_LANG') initLang: string) { this._currentLang = initLang || this.getBrowserLang(); } get lang() : string { return this._currentLang; } set lang(newLang: string) { this._currentLang = newLang; this.http.get(this._format(this.URL_TPL, newLang)).subscribe((data) => { this._messages = data; this.reloadTexts(); }); } isLoaded() : boolean { return !!this._messages } getBrowserLang() : string { var l; if (!navigator) return 'en'; if (navigator.languages && navigator.languages.length) { l = navigator.languages[0]; } else { l = navigator.language || 'en'; } l = l.replace(/-.*/gi, ''); if (l !== 'en' && l !== 'es') return 'en'; return l; } /** * It works similar to MessageFormat in Java */ _format(str: string, ...params: Array) { return str.replace(/\{(\d+)\}/g, function(match, index) { return params[index]; }); }; reloadTexts() : void { this._elements.forEach((ele: ElementRef) => { var txt = ele.nativeElement.getAttribute('i18n'); if (!!txt) { ele.nativeElement.textContent = this.get(txt); } }) } add(ele: ElementRef) { this._elements.push(ele); } /** * It accepts direct messages and templates: * { * "hello": "hola", * "Hello {0}!!: "Hola {0}!!" * } * $L.get('hello'); // This returns "hola" * $L.get('Hello {0}!!', 'John'); // This returns: "Hola John!!" if language is spanish */ get(msg: string) : string { if (msg == null) { return ''; } msg = msg.trim(); var trans_msg = msg; if (this.isLoaded()) { if (this._messages[msg]) { trans_msg = this._messages[msg]; } else if (this._messages[msg.toLowerCase()]) { trans_msg = this._messages[msg.toLowerCase()]; } else { this._currentLang !== 'es' && console.error("Missing i18 key: " + msg); trans_msg = msg; } } // Enviar evento cuando el idioma cambia al $rootScope if (arguments.length === 1) return trans_msg; var params = Array.prototype.slice.call(arguments, 1); return this._format.apply(trans_msg, params); } } @Directive({ selector: '[i18n]' }) export class I18nDirective { constructor(private el: ElementRef, private renderer: Renderer, private $L: LocaleService) { } ngAfterViewChecked() { var txt = this.el.nativeElement.getAttribute('i18n') || this.el.nativeElement.textContent; this.renderer.setElementProperty(this.el.nativeElement, 'i18n', txt.trim()); this.$L.add(this.el); this.renderer.setElementProperty(this.el.nativeElement, 'innerHTML', this.$L.get(txt)); } } @NgModule({ providers: [ LocaleService ] }) export class LocaleServiceModule { static withConfig(initLang?: string): ModuleWithProviders { console.log('Init lang with ' + initLang); return { ngModule: LocaleServiceModule, providers: [ { provide: 'INITIAL_LANG', useValue: initLang } ] } } }