angular-l10n
Version:
An Angular library to translate messages, dates and numbers
529 lines • 19 kB
JavaScript
/**
* @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