UNPKG

angular-l10n

Version:

An Angular library to translate messages, dates and numbers

529 lines 19 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Injectable, Inject } from '@angular/core'; import { Observable, Subject, BehaviorSubject, race, combineLatest, merge, concat } from 'rxjs'; import { filter, map } from 'rxjs/operators'; import { LocaleService } from './locale.service'; import { TranslationProvider } from './translation-provider'; import { TranslationHandler } from './translation-handler'; import { InjectorRef } from '../models/injector-ref'; import { L10N_CONFIG } from "../models/l10n-config"; import { mergeDeep } from '../models/merge-deep'; import { ProviderType } from '../models/types'; /** * @record */ export function ITranslationService() { } if (false) { /** @type {?} */ ITranslationService.prototype.translationError; /** * @return {?} */ ITranslationService.prototype.getConfiguration = function () { }; /** * @return {?} */ ITranslationService.prototype.init = function () { }; /** * @return {?} */ ITranslationService.prototype.loadTranslation = function () { }; /** * @return {?} */ ITranslationService.prototype.translationChanged = function () { }; /** * @return {?} */ ITranslationService.prototype.latestTranslation = function () { }; /** * @param {?} keys * @param {?=} args * @param {?=} lang * @return {?} */ ITranslationService.prototype.translate = function (keys, args, lang) { }; /** * @param {?} keys * @param {?=} args * @param {?=} lang * @return {?} */ ITranslationService.prototype.translateAsync = function (keys, args, lang) { }; /** * @param {?} key * @param {?=} lang * @return {?} */ ITranslationService.prototype.has = function (key, lang) { }; } /** * Manages the translation data. */ var TranslationService = /** @class */ (function () { function TranslationService(configuration, locale, translationProvider, translationHandler, injector) { this.configuration = configuration; this.locale = locale; this.translationProvider = translationProvider; this.translationHandler = translationHandler; this.injector = injector; /** * Fired when the translation data could not been loaded. Returns the error. */ this.translationError = new Subject(); this.translation = new BehaviorSubject(''); /** * The translation data: {language: {key: value}}. */ this.translationData = {}; this.injector.translations.push(this); } /** * @return {?} */ TranslationService.prototype.getConfiguration = /** * @return {?} */ function () { return this.configuration.translation; }; /** * @return {?} */ TranslationService.prototype.init = /** * @return {?} */ function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: // When the language or the default locale changes, loads translation data. race(this.locale.languageCodeChanged, this.locale.defaultLocaleChanged).subscribe(function () { _this.loadTranslation() .catch(function (error) { return null; }); }); return [4 /*yield*/, this.loadTranslation() .catch(function (error) { throw error; })]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; /** * Forces the translation loading for the current language. */ /** * Forces the translation loading for the current language. * @return {?} */ TranslationService.prototype.loadTranslation = /** * Forces the translation loading for the current language. * @return {?} */ function () { return tslib_1.__awaiter(this, void 0, void 0, function () { var language; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (this.configuration.translation.composedLanguage) { language = this.locale.composeLocale(this.configuration.translation.composedLanguage); } else { language = this.locale.getCurrentLanguage(); } if (!language) return [3 /*break*/, 2]; this.translationData = {}; if (this.configuration.translation.translationData) { this.getTranslation(language); } if (!this.configuration.translation.providers) return [3 /*break*/, 2]; return [4 /*yield*/, this.getTranslationAsync(language) .toPromise() .catch(function (error) { throw error; })]; case 1: _a.sent(); _a.label = 2; case 2: return [2 /*return*/]; } }); }); }; /** * Fired when the translation data has been loaded. Returns the translation language. */ /** * Fired when the translation data has been loaded. Returns the translation language. * @return {?} */ TranslationService.prototype.translationChanged = /** * Fired when the translation data has been loaded. Returns the translation language. * @return {?} */ function () { return this.translation.asObservable(); }; /** * Fired when the latest 'translationChanged' is emitted. Returns the translation language. * Used when the reference to the service is not known, as in decorators. */ /** * Fired when the latest 'translationChanged' is emitted. Returns the translation language. * Used when the reference to the service is not known, as in decorators. * @return {?} */ TranslationService.prototype.latestTranslation = /** * Fired when the latest 'translationChanged' is emitted. Returns the translation language. * Used when the reference to the service is not known, as in decorators. * @return {?} */ function () { /** @type {?} */ var sequencesOfTranslation = []; for (var _i = 0, _a = this.injector.translations; _i < _a.length; _i++) { var translation = _a[_i]; sequencesOfTranslation.push(translation.translationChanged()); } return combineLatest(sequencesOfTranslation).pipe(filter(function (languages) { return languages.length == sequencesOfTranslation.length && languages.every(function (lang, i, arr) { return lang == arr[0]; }); }), map(function (languages) { return languages[0]; })); }; /** * Translates a key or an array of keys. * @param keys The key or an array of keys to be translated * @param args Optional parameters contained in the key * @param lang The current language of the service is used by default * @return The translated value or an object: {key: value} */ /** * Translates a key or an array of keys. * @param {?} keys The key or an array of keys to be translated * @param {?=} args Optional parameters contained in the key * @param {?=} lang The current language of the service is used by default * @return {?} The translated value or an object: {key: value} */ TranslationService.prototype.translate = /** * Translates a key or an array of keys. * @param {?} keys The key or an array of keys to be translated * @param {?=} args Optional parameters contained in the key * @param {?=} lang The current language of the service is used by default * @return {?} The translated value or an object: {key: value} */ function (keys, args, lang) { if (Array.isArray(keys)) { /** @type {?} */ var data = {}; for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var key = keys_1[_i]; data[key] = this.translateKey(key, args, lang || this.translation.getValue()); } return data; } return this.translateKey(keys, args, lang || this.translation.getValue()); }; /** * @param {?} keys * @param {?=} args * @param {?=} lang * @return {?} */ TranslationService.prototype.translateAsync = /** * @param {?} keys * @param {?=} args * @param {?=} lang * @return {?} */ function (keys, args, lang) { var _this = this; return new Observable(function (observer) { /** @type {?} */ var values = _this.translate(keys, args, lang); observer.next(values); observer.complete(); }); }; /** * Checks if a translation exists. * @param key The key to be tested * @param lang The current language of the service is used by default */ /** * Checks if a translation exists. * @param {?} key The key to be tested * @param {?=} lang The current language of the service is used by default * @return {?} */ TranslationService.prototype.has = /** * Checks if a translation exists. * @param {?} key The key to be tested * @param {?=} lang The current language of the service is used by default * @return {?} */ function (key, lang) { if (lang === void 0) { lang = this.translation.getValue(); } /** @type {?} */ var path = key; /** @type {?} */ var translation = { nested: this.translationData[lang] }; if (translation.nested) { key = this.extractKey(translation, path); return typeof translation.nested[key] !== "undefined"; } return false; }; /** * @param {?} key * @param {?} args * @param {?} lang * @return {?} */ TranslationService.prototype.translateKey = /** * @param {?} key * @param {?} args * @param {?} lang * @return {?} */ function (key, args, lang) { // I18n plural. if (this.configuration.translation.i18nPlural && /^\d+\b/.exec(key)) { return this.translateI18nPlural(key, args, lang); } return this.getValue(key, args, lang); }; /** * @param {?} key * @param {?} args * @param {?} lang * @return {?} */ TranslationService.prototype.getValue = /** * @param {?} key * @param {?} args * @param {?} lang * @return {?} */ function (key, args, lang) { /** @type {?} */ var path = key; /** @type {?} */ var translation = { nested: this.translationData[lang] }; /** @type {?} */ var value = null; if (translation.nested) { key = this.extractKey(translation, path); value = typeof translation.nested[key] === "undefined" ? translation.nested[this.configuration.translation.missingKey || ""] : translation.nested[key]; } return this.translationHandler.parseValue(path, key, value, args, lang); }; /** * @param {?} translation * @param {?} path * @return {?} */ TranslationService.prototype.extractKey = /** * @param {?} translation * @param {?} path * @return {?} */ function (translation, path) { if (!this.configuration.translation.composedKeySeparator) return path; // Composed key. /** @type {?} */ var sequences = path.split(this.configuration.translation.composedKeySeparator); /** @type {?} */ var key = (/** @type {?} */ (sequences.shift())); while (sequences.length > 0 && translation.nested[key]) { translation.nested = translation.nested[key]; key = (/** @type {?} */ (sequences.shift())); } return key; }; /** * @param {?} key * @param {?} args * @param {?} lang * @return {?} */ TranslationService.prototype.translateI18nPlural = /** * @param {?} key * @param {?} args * @param {?} lang * @return {?} */ function (key, args, lang) { /** @type {?} */ var keyText = key.replace(/^\d+\b/, ""); keyText = keyText.trim(); /** @type {?} */ var keyNumber = parseFloat(key); if (!isNaN(keyNumber)) { key = key.replace(/^\d+/, this.locale.formatDecimal(keyNumber)); } return key.replace(keyText, this.getValue(keyText, args, lang)); }; /** * @param {?} language * @return {?} */ TranslationService.prototype.getTranslation = /** * @param {?} language * @return {?} */ function (language) { /** @type {?} */ var translations = (/** @type {?} */ (this.configuration.translation.translationData)).filter(function (value) { return value.languageCode == language; }); for (var _i = 0, translations_1 = translations; _i < translations_1.length; _i++) { var translation = translations_1[_i]; this.addData(translation.data, language); } if (!this.configuration.translation.providers) { this.releaseTranslation(language); } }; /** * @param {?} language * @return {?} */ TranslationService.prototype.getTranslationAsync = /** * @param {?} language * @return {?} */ function (language) { var _this = this; return new Observable(function (observer) { /** @type {?} */ var sequencesOfOrderedTranslationData = []; /** @type {?} */ var sequencesOfTranslationData = []; for (var _i = 0, _a = (/** @type {?} */ (_this.configuration.translation.providers)); _i < _a.length; _i++) { var provider = _a[_i]; if (typeof provider.type !== "undefined" && provider.type == ProviderType.Fallback) { /** @type {?} */ var fallbackLanguage = language; if (provider.fallbackLanguage) { fallbackLanguage = _this.locale.composeLocale(provider.fallbackLanguage); } sequencesOfOrderedTranslationData.push(_this.translationProvider.getTranslation(fallbackLanguage, provider)); } else { sequencesOfTranslationData.push(_this.translationProvider.getTranslation(language, provider)); } } // Merges all the sequences into a single observable sequence. /** @type {?} */ var mergedSequencesOfTranslationData = merge.apply(void 0, sequencesOfTranslationData); // Adds to ordered sequences. sequencesOfOrderedTranslationData.push(mergedSequencesOfTranslationData); concat.apply(void 0, sequencesOfOrderedTranslationData).subscribe(function (data) { _this.addData(data, language); }, function (error) { _this.handleError(error, language); observer.error(error); observer.complete(); }, function () { _this.releaseTranslation(language); observer.next(null); observer.complete(); }); }); }; /** * @param {?} data * @param {?} language * @return {?} */ TranslationService.prototype.addData = /** * @param {?} data * @param {?} language * @return {?} */ function (data, language) { this.translationData[language] = typeof this.translationData[language] !== "undefined" ? mergeDeep(this.translationData[language], data) : data; }; /** * @param {?} language * @return {?} */ TranslationService.prototype.releaseTranslation = /** * @param {?} language * @return {?} */ function (language) { this.translation.next(language); }; /** * @param {?} error * @param {?} language * @return {?} */ TranslationService.prototype.handleError = /** * @param {?} error * @param {?} language * @return {?} */ function (error, language) { if (this.configuration.translation.rollbackOnError) { this.locale.rollback(); } else { this.releaseTranslation(language); } this.translationError.next(error); }; TranslationService.decorators = [ { type: Injectable } ]; /** @nocollapse */ TranslationService.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: Inject, args: [L10N_CONFIG,] }] }, { type: LocaleService }, { type: TranslationProvider }, { type: TranslationHandler }, { type: InjectorRef } ]; }; return TranslationService; }()); export { TranslationService }; if (false) { /** * Fired when the translation data could not been loaded. Returns the error. * @type {?} */ TranslationService.prototype.translationError; /** @type {?} */ TranslationService.prototype.translation; /** * The translation data: {language: {key: value}}. * @type {?} */ TranslationService.prototype.translationData; /** @type {?} */ TranslationService.prototype.configuration; /** @type {?} */ TranslationService.prototype.locale; /** @type {?} */ TranslationService.prototype.translationProvider; /** @type {?} */ TranslationService.prototype.translationHandler; /** @type {?} */ TranslationService.prototype.injector; } //# sourceMappingURL=translation.service.js.map