UNPKG

@fabioguelfi/angular-translate

Version:

A lightweight internationalization library for Angular applications

460 lines (448 loc) 13.6 kB
import { InjectionToken, Inject, Injectable, Directive, ElementRef, Input, Pipe, NgModule } from '@angular/core'; import { HttpClient, HttpClientModule } from '@angular/common/http'; import { BehaviorSubject, Subject, of, from, combineLatest } from 'rxjs'; import { filter, switchMap, switchMapTo, take, takeUntil } from 'rxjs/operators'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ CONFIG = new InjectionToken('config'); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class LoaderService { /** * @param {?} http * @param {?} config */ constructor(http, config) { this.http = http; this.config = config; this.path = '/assets/languages/'; this.extension = '.json'; this.path = config.path ? config.path : this.path; } /** * @param {?} fileName * @return {?} */ getFile(fileName) { return this.http.get(this.path + fileName + this.extension); } } LoaderService.decorators = [ { type: Injectable } ]; /** @nocollapse */ LoaderService.ctorParameters = () => [ { type: HttpClient, }, { type: undefined, decorators: [{ type: Inject, args: [CONFIG,] },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** @enum {string} */ const CONSTANTS = { EXIT: 'EXIT', }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class TranslateService { /** * @param {?} http * @param {?} config */ constructor(http, config) { this.http = http; this.config = config; this.translations = {}; this.translationsLoaded = new BehaviorSubject(false); this.matcher = key => new RegExp('{{\\s?[\\b' + key + '\\b]*\\s?}}', 'gm'); this.loaderService = new LoaderService(http, config); } /** * @return {?} */ getBrowserLanguage() { let /** @type {?} */ browserLanguage = window.navigator.languages ? window.navigator.languages[0] : window.navigator.language; if (browserLanguage.indexOf('-') !== -1) { browserLanguage = browserLanguage.split('-')[0]; } if (browserLanguage.indexOf('_') !== -1) { browserLanguage = browserLanguage.split('_')[0]; } return browserLanguage; } /** * @param {?} fileName * @return {?} */ setDefault(fileName) { this.defaultKey = fileName; this.defaultPrefix = fileName.split('-')[0]; if (this.translations[this.defaultKey]) { this.translationsLoaded.next(true); } else { this.translationsLoaded.next(false); this.loaderService.getFile(fileName) .subscribe(translations => { this.translations[this.defaultKey] = translations; this.translationsLoaded.next(true); }); } } /** * @param {?} fileName * @return {?} */ setOverride(fileName) { this.overrideKey = fileName; if (this.translations[this.overrideKey]) { this.translationsLoaded.next(true); } else { this.loaderService.getFile(fileName) .subscribe(translations => { this.translations[this.overrideKey] = translations; this.translationsLoaded.next(true); }); } } /** * @param {?} keyPaths * @return {?} */ get(keyPaths) { return this.translationsLoaded.pipe(filter(Boolean), switchMapTo(keyPaths instanceof Array ? this.getAll(keyPaths) : this.getOne(keyPaths))); } /** * @param {?} keyPaths * @param {?} fileName * @return {?} */ getByFileName(keyPaths, fileName) { const /** @type {?} */ translationLoaded = new Subject(); const /** @type {?} */ defaultFileName = `${this.defaultPrefix}-${fileName.split('-')[1]}`; this.loaderService.getFile(fileName).pipe(file => combineLatest(file, this.loaderService.getFile(defaultFileName)), filter(([file, defaultFile]) => [file, defaultFile].indexOf(undefined) === -1), take(1)).subscribe(([translations, defaultTranslations]) => { this.translations[fileName] = translations; this.translations[defaultFileName] = defaultTranslations; translationLoaded.next(fileName); }, () => { this.loaderService.getFile(defaultFileName) .pipe(take(1)) .subscribe(translations => { this.translations[defaultFileName] = translations; translationLoaded.next(defaultFileName); }); }); return translationLoaded.pipe(switchMap(overrideFileName => keyPaths instanceof Array ? this.getAll(keyPaths, overrideFileName, defaultFileName) : this.getOne(keyPaths, overrideFileName, defaultFileName))); } /** * @param {?} keyPath * @param {?=} fileName * @param {?=} defaultKey * @return {?} */ getOne(keyPath, fileName = this.overrideKey, defaultKey = this.defaultKey) { return from([this.read(keyPath, {}, fileName, defaultKey)]); } /** * @param {?} keyPaths * @param {?=} fileName * @param {?=} defaultKey * @return {?} */ getAll(keyPaths, fileName = this.overrideKey, defaultKey = this.defaultKey) { return of(keyPaths.reduce((acc, keyPath) => (Object.assign({}, acc, { [keyPath]: this.read(keyPath, {}, fileName, defaultKey) })), {})); } /** * @param {?} keyPath * @param {?=} params * @param {?=} overrideKey * @param {?=} defaultKey * @return {?} */ read(keyPath, params = {}, overrideKey = this.overrideKey, defaultKey = this.defaultKey) { let /** @type {?} */ value = CONSTANTS.EXIT; const /** @type {?} */ path = keyPath.split('.'); if (this.translations[overrideKey]) { value = this.readValue(path, this.translations[overrideKey]); if (value === CONSTANTS.EXIT) { value = this.readValue(path, this.translations[defaultKey]); } } else if (this.translations[defaultKey]) { value = this.readValue(path, this.translations[defaultKey]); } if (Boolean(params) && params !== {}) { value = Object.keys(params) .reduce((final, key) => final.replace(this.matcher(key), params[key]), value); } if (value === CONSTANTS.EXIT) { console.warn('Unknown Key: ', keyPath); return keyPath; } return value; } /** * @param {?} path * @param {?} translation * @return {?} */ readValue(path, translation) { const /** @type {?} */ length = path.length; for (let /** @type {?} */ i = 0; i < length; i++) { translation = translation && translation[path[i]] ? translation[path[i]] : CONSTANTS.EXIT; if (translation === CONSTANTS.EXIT) { break; } } return translation; } /** * @param {?} a * @param {?} b * @return {?} */ isEquivalent(a, b) { if (!Boolean(a) || !Boolean(b)) { return false; } const /** @type {?} */ aProps = Object.getOwnPropertyNames(a); const /** @type {?} */ bProps = Object.getOwnPropertyNames(b); if (aProps.length !== bProps.length) { return false; } for (let /** @type {?} */ i = 0; i < aProps.length; i++) { const /** @type {?} */ propName = aProps[i]; if (a[propName] !== b[propName]) { return false; } } return true; } } TranslateService.decorators = [ { type: Injectable } ]; /** @nocollapse */ TranslateService.ctorParameters = () => [ { type: HttpClient, }, { type: undefined, decorators: [{ type: Inject, args: [CONFIG,] },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class TranslateDirective { /** * @param {?} element * @param {?} translateService */ constructor(element, translateService) { this.element = element; this.translateService = translateService; this.unsubscribe = new Subject(); this.translationLoaded$ = this.translateService.translationsLoaded .pipe(takeUntil(this.unsubscribe)); } /** * @param {?} params * @return {?} */ set params(params) { if (!this.translateService.isEquivalent(this.translateParams, params)) { this.translateParams = params; if (this.translateParams) { this.runOneCheck(this.keyPath, this.translateParams); } } } ; /** * @return {?} */ ngAfterViewInit() { this.keyPath = this.element.nativeElement.textContent ? this.element.nativeElement.textContent.trim() : ''; this.element.nativeElement.textContent = ''; this.registerKeyChecker(this.keyPath); } /** * @return {?} */ ngOnDestroy() { this.unsubscribe.next(); this.unsubscribe.complete(); } /** * @param {?} keyPath * @return {?} */ registerKeyChecker(keyPath) { this.translationLoaded$ .subscribe(isLoaded => this.doCheck(isLoaded, keyPath, this.translateParams)); } /** * @param {?} keyPath * @param {?} params * @return {?} */ runOneCheck(keyPath, params) { if (keyPath) { this.translationLoaded$ .pipe(take(1)) .subscribe(isLoaded => this.doCheck(isLoaded, keyPath, params)); } } /** * @param {?} isLoaded * @param {?} keyPath * @param {?} params * @return {?} */ doCheck(isLoaded, keyPath, params) { if (isLoaded) { const /** @type {?} */ readValue = keyPath !== '' ? this.translateService.read(keyPath, params) : ''; this.element.nativeElement.textContent = readValue === keyPath ? '' : readValue; } } } TranslateDirective.decorators = [ { type: Directive, args: [{ selector: '[translate]' },] } ]; /** @nocollapse */ TranslateDirective.ctorParameters = () => [ { type: ElementRef, }, { type: TranslateService, }, ]; TranslateDirective.propDecorators = { "params": [{ type: Input, args: ['translate',] },], }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class TranslatePipe { /** * @param {?} translateService */ constructor(translateService) { this.translateService = translateService; this.translation = ''; this.unsubscribe = new Subject(); this.translationLoaded$ = translateService.translationsLoaded.pipe(filter(Boolean), takeUntil(this.unsubscribe)); } /** * @param {?} val * @param {?} args * @return {?} */ transform(val, args) { this.translationLoaded$.subscribe(() => { const /** @type {?} */ readValue = val ? this.translateService.read(val, args) : ''; this.translation = readValue === val ? this.translation : readValue; }); return this.translation; } /** * @return {?} */ ngOnDestroy() { this.unsubscribe.next(); this.unsubscribe.complete(); } } TranslatePipe.decorators = [ { type: Pipe, args: [{ name: 'translate', pure: false },] } ]; /** @nocollapse */ TranslatePipe.ctorParameters = () => [ { type: TranslateService, }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class TranslateModule { /** * @param {?=} config * @return {?} */ static forRoot(config = {}) { return { ngModule: TranslateModule, providers: [ TranslateService, LoaderService, { provide: CONFIG, useValue: config } ] }; } ; /** * @return {?} */ static forChild() { return { ngModule: TranslateModule }; } ; } TranslateModule.decorators = [ { type: NgModule, args: [{ imports: [HttpClientModule], declarations: [ TranslateDirective, TranslatePipe ], exports: [ TranslateDirective, TranslatePipe ] },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ const /** @type {?} */ translations = { 'default-en': { 'BODY': { 'KNOWN_KEY': 'Known key example' } } }; const /** @type {?} */ LoaderServiceMock = { path: '/assets/language', extension: '.json', http: null, config: null, getFile: (key) => of(translations[key]) }; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ export { TranslateModule, TranslateService, TranslateDirective, TranslatePipe, LoaderService, LoaderServiceMock, CONFIG as ɵa }; //# sourceMappingURL=angular-translate.js.map