UNPKG

@ngneat/transloco

Version:

The internationalization (i18n) library for Angular

1,262 lines 96.3 kB
/** * @fileoverview added by tsickle * Generated from: lib/transloco.service.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import * as tslib_1 from "tslib"; import { Inject, Injectable, Optional } from '@angular/core'; import { BehaviorSubject, combineLatest, EMPTY, forkJoin, from, of, Subject } from 'rxjs'; import { catchError, map, retry, shareReplay, switchMap, tap } from 'rxjs/operators'; import { DefaultLoader, TRANSLOCO_LOADER } from './transloco.loader'; import { TRANSLOCO_TRANSPILER } from './transloco.transpiler'; import { flatten, isEmpty, isNil, isScopeObject, isString, size, toCamelCase, unflatten } from './helpers'; import { defaultConfig, TRANSLOCO_CONFIG } from './transloco.config'; import { TRANSLOCO_MISSING_HANDLER } from './transloco-missing-handler'; import { TRANSLOCO_INTERCEPTOR } from './transloco.interceptor'; import { TRANSLOCO_FALLBACK_STRATEGY } from './transloco-fallback-strategy'; import { mergeConfig } from './merge-config'; import { getEventPayload, getLangFromScope, getScopeFromLang, resolveInlineLoader } from './shared'; import { getFallbacksLoaders } from './get-fallbacks-loaders'; import { resolveLoader } from './resolve-loader'; import * as i0 from "@angular/core"; import * as i1 from "./transloco.loader"; import * as i2 from "./transloco.transpiler"; import * as i3 from "./transloco-missing-handler"; import * as i4 from "./transloco.interceptor"; import * as i5 from "./transloco.config"; import * as i6 from "./transloco-fallback-strategy"; /** @type {?} */ var service; /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ export function translate(key, params, lang) { if (params === void 0) { params = {}; } return service.translate(key, params, lang); } var TranslocoService = /** @class */ (function () { function TranslocoService(loader, parser, missingHandler, interceptor, userConfig, fallbackStrategy) { var _this = this; this.loader = loader; this.parser = parser; this.missingHandler = missingHandler; this.interceptor = interceptor; this.userConfig = userConfig; this.fallbackStrategy = fallbackStrategy; this.translations = new Map(); this.cache = new Map(); this.firstFallbackLang = null; this.availableLangs = []; this.isResolvedMissingOnce = false; this.events = new Subject(); this.events$ = this.events.asObservable(); this.failedLangs = new Set(); if (!this.loader) { this.loader = new DefaultLoader(this.translations); } service = this; this.mergedConfig = mergeConfig(defaultConfig, userConfig); this.setAvailableLangs(this.mergedConfig.availableLangs); this.setFallbackLangForMissingTranslation(this.mergedConfig); this.setDefaultLang(this.mergedConfig.defaultLang); this.lang = new BehaviorSubject(this.getDefaultLang()); // Don't use distinctUntilChanged as we need the ability to update // the value when using setTranslation or setTranslationKeys this.langChanges$ = this.lang.asObservable(); /** * When we have a failure, we want to define the next language that succeeded as the active */ this.subscription = this.events$.subscribe((/** * @param {?} e * @return {?} */ function (e) { if (e.type === 'translationLoadSuccess' && e.wasFailure) { // Handle scoped lang /** @type {?} */ var lang = getLangFromScope(e.payload.lang); _this.setActiveLang(lang); } })); } Object.defineProperty(TranslocoService.prototype, "config", { get: /** * @return {?} */ function () { return this.mergedConfig; }, enumerable: true, configurable: true }); /** * @return {?} */ TranslocoService.prototype.getDefaultLang = /** * @return {?} */ function () { return this.defaultLang; }; /** * @param {?} lang * @return {?} */ TranslocoService.prototype.setDefaultLang = /** * @param {?} lang * @return {?} */ function (lang) { this.defaultLang = lang; }; /** * @return {?} */ TranslocoService.prototype.getActiveLang = /** * @return {?} */ function () { return this.lang.getValue(); }; /** * @template THIS * @this {THIS} * @param {?} lang * @return {THIS} */ TranslocoService.prototype.setActiveLang = /** * @template THIS * @this {THIS} * @param {?} lang * @return {THIS} */ function (lang) { (/** @type {?} */ (this)).parser.onLangChanged && (/** @type {?} */ (this)).parser.onLangChanged(lang); (/** @type {?} */ (this)).lang.next(lang); return (/** @type {?} */ (this)); }; /** * @param {?} langs * @return {?} */ TranslocoService.prototype.setAvailableLangs = /** * @param {?} langs * @return {?} */ function (langs) { this.availableLangs = langs; }; /** * Gets the available languages. * * @returns * An array of the available languages. Can be either a `string[]` or a `{ id: string; label: string }[]` * depending on how the available languages are set in your module. */ /** * Gets the available languages. * * @return {?} * An array of the available languages. Can be either a `string[]` or a `{ id: string; label: string }[]` * depending on how the available languages are set in your module. */ TranslocoService.prototype.getAvailableLangs = /** * Gets the available languages. * * @return {?} * An array of the available languages. Can be either a `string[]` or a `{ id: string; label: string }[]` * depending on how the available languages are set in your module. */ function () { return this.availableLangs; }; /** * @param {?} path * @param {?=} options * @return {?} */ TranslocoService.prototype.load = /** * @param {?} path * @param {?=} options * @return {?} */ function (path, options) { var _this = this; if (options === void 0) { options = {}; } if (this.cache.has(path) === false) { /** @type {?} */ var loadTranslation = void 0; /** @type {?} */ var isScope = this._isLangScoped(path); /** @type {?} */ var scope = isScope ? getScopeFromLang(path) : null; if (this.useFallbackTranslation(path)) { // if the path is scope the fallback should be `scope/fallbackLang`; /** @type {?} */ var fallback = isScope ? scope + "/" + this.firstFallbackLang : this.firstFallbackLang; /** @type {?} */ var loaders = getFallbacksLoaders(path, fallback, this.loader, options.inlineLoader, { scope: scope }); loadTranslation = forkJoin(loaders); } else { /** @type {?} */ var loader = resolveLoader(path, this.loader, options.inlineLoader, { scope: scope }); loadTranslation = from(loader); } /** @type {?} */ var load$ = loadTranslation.pipe(retry(this.config.failedRetries), tap((/** * @param {?} translation * @return {?} */ function (translation) { if (Array.isArray(translation)) { translation.forEach((/** * @param {?} t * @return {?} */ function (t) { _this.handleSuccess(t.lang, t.translation); // Save the fallback in cache so we'll not create a redundant request if (t.lang !== path) { _this.cache.set(t.lang, of({})); } })); return; } _this.handleSuccess(path, translation); })), catchError((/** * @return {?} */ function () { return _this.handleFailure(path, options); })), shareReplay(1)); this.cache.set(path, load$); } return this.cache.get(path); }; /** * Gets the instant translated value of a key * * @example * * translate<string>('hello') * translate('hello', { value: 'value' }) * translate<string[]>(['hello', 'key']) * translate('hello', { }, 'en') * translate('scope.someKey', { }, 'en') */ /** * Gets the instant translated value of a key * * \@example * * translate<string>('hello') * translate('hello', { value: 'value' }) * translate<string[]>(['hello', 'key']) * translate('hello', { }, 'en') * translate('scope.someKey', { }, 'en') * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ TranslocoService.prototype.translate = /** * Gets the instant translated value of a key * * \@example * * translate<string>('hello') * translate('hello', { value: 'value' }) * translate<string[]>(['hello', 'key']) * translate('hello', { }, 'en') * translate('scope.someKey', { }, 'en') * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ function (key, params, lang) { var _this = this; if (params === void 0) { params = {}; } if (lang === void 0) { lang = this.getActiveLang(); } if (!key) return (/** @type {?} */ (key)); var _a = this.resolveLangAndScope(lang), scope = _a.scope, resolveLang = _a.resolveLang; if (Array.isArray(key)) { return (/** @type {?} */ (key.map((/** * @param {?} k * @return {?} */ function (k) { return _this.translate(scope ? scope + "." + k : k, params, resolveLang); })))); } key = scope ? scope + "." + key : key; /** @type {?} */ var translation = this.getTranslation(resolveLang); /** @type {?} */ var value = translation[key]; if (!value) { return this._handleMissingKey(key, value, params); } return this.parser.transpile(value, params, translation); }; /** * Gets the translated value of a key as observable * * @example * * selectTranslate<string>('hello').subscribe(value => ...) * selectTranslate<string>('hello', {}, 'es').subscribe(value => ...) * selectTranslate<string>('hello', {}, 'todos').subscribe(value => ...) * selectTranslate<string>('hello', {}, { scope: 'todos' }).subscribe(value => ...) * */ /** * Gets the translated value of a key as observable * * \@example * * selectTranslate<string>('hello').subscribe(value => ...) * selectTranslate<string>('hello', {}, 'es').subscribe(value => ...) * selectTranslate<string>('hello', {}, 'todos').subscribe(value => ...) * selectTranslate<string>('hello', {}, { scope: 'todos' }).subscribe(value => ...) * * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @param {?=} _isObject * @return {?} */ TranslocoService.prototype.selectTranslate = /** * Gets the translated value of a key as observable * * \@example * * selectTranslate<string>('hello').subscribe(value => ...) * selectTranslate<string>('hello', {}, 'es').subscribe(value => ...) * selectTranslate<string>('hello', {}, 'todos').subscribe(value => ...) * selectTranslate<string>('hello', {}, { scope: 'todos' }).subscribe(value => ...) * * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @param {?=} _isObject * @return {?} */ function (key, params, lang, _isObject) { var _this = this; if (_isObject === void 0) { _isObject = false; } /** @type {?} */ var inlineLoader = null; /** @type {?} */ var load = (/** * @param {?} lang * @param {?=} options * @return {?} */ function (lang, options) { return _this.load(lang, options).pipe(map((/** * @return {?} */ function () { return (_isObject ? _this.translateObject(key, params, lang) : _this.translate(key, params, lang)); }))); }); if (isNil(lang)) { return this.langChanges$.pipe(switchMap((/** * @param {?} lang * @return {?} */ function (lang) { return load(lang); }))); } if (isScopeObject(lang)) { // it's a scope object. /** @type {?} */ var providerScope = (/** @type {?} */ (lang)); lang = providerScope.scope; inlineLoader = resolveInlineLoader(providerScope, providerScope.scope); } lang = (/** @type {?} */ (lang)); if (this.isLang(lang) || this.isScopeWithLang(lang)) { return load(lang); } // it's a scope /** @type {?} */ var scope = lang; return this.langChanges$.pipe(switchMap((/** * @param {?} lang * @return {?} */ function (lang) { return load(scope + "/" + lang, { inlineLoader: inlineLoader }); }))); }; /** * Whether the scope with lang * * @example * * todos/en => true * todos => false */ /** * Whether the scope with lang * * \@example * * todos/en => true * todos => false * @private * @param {?} lang * @return {?} */ TranslocoService.prototype.isScopeWithLang = /** * Whether the scope with lang * * \@example * * todos/en => true * todos => false * @private * @param {?} lang * @return {?} */ function (lang) { return this.isLang(getLangFromScope(lang)); }; /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ TranslocoService.prototype.translateObject = /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ function (key, params, lang) { var _this = this; if (lang === void 0) { lang = this.getActiveLang(); } var e_1, _a; if (isString(key) || Array.isArray(key)) { if (Array.isArray(key)) { return (/** @type {?} */ (key.map((/** * @param {?} k * @return {?} */ function (k) { return _this.translateObject(scope_1 ? scope_1 + "." + k : k, params, resolveLang_1); })))); } var _b = this.resolveLangAndScope(lang), resolveLang_1 = _b.resolveLang, scope_1 = _b.scope; /** @type {?} */ var translation = this.getTranslation(resolveLang_1); key = scope_1 ? scope_1 + "." + key : key; /** @type {?} */ var value = unflatten(this.getObjectByKey(translation, key)); /* If an empty object was returned we want to try and translate the key as a string and not an object */ return isEmpty(value) ? this.translate(key, params, lang) : this.parser.transpile(value, params, translation); } /** @type {?} */ var translations = []; try { for (var _c = tslib_1.__values(this.getEntries(key)), _d = _c.next(); !_d.done; _d = _c.next()) { var _e = tslib_1.__read(_d.value, 2), _key = _e[0], _params = _e[1]; translations.push(this.translateObject(_key, _params, lang)); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_1) throw e_1.error; } } return translations; }; /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ TranslocoService.prototype.selectTranslateObject = /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ function (key, params, lang) { var _this = this; if (isString(key) || Array.isArray(key)) { return this.selectTranslate(key, params, lang, true); } var _a = tslib_1.__read(this.getEntries(key)), _b = tslib_1.__read(_a[0], 2), firstKey = _b[0], firstParams = _b[1], rest = _a.slice(1); /* In order to avoid subscribing multiple times to the load language event by calling selectTranslateObject for each pair, * we listen to when the first key has been translated (the language is loaded) and translate the rest synchronously */ return this.selectTranslateObject(firstKey, firstParams, lang).pipe(map((/** * @param {?} value * @return {?} */ function (value) { var e_2, _a; /** @type {?} */ var translations = [value]; try { for (var rest_1 = tslib_1.__values(rest), rest_1_1 = rest_1.next(); !rest_1_1.done; rest_1_1 = rest_1.next()) { var _b = tslib_1.__read(rest_1_1.value, 2), _key = _b[0], _params = _b[1]; translations.push(_this.translateObject(_key, _params, lang)); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (rest_1_1 && !rest_1_1.done && (_a = rest_1.return)) _a.call(rest_1); } finally { if (e_2) throw e_2.error; } } return translations; }))); }; /** * @param {?=} langOrScope * @return {?} */ TranslocoService.prototype.getTranslation = /** * @param {?=} langOrScope * @return {?} */ function (langOrScope) { if (langOrScope) { if (this.isLang(langOrScope)) { return this.translations.get(langOrScope) || {}; } else { // This is a scope, build the scope value from the translation object var _a = this.resolveLangAndScope(langOrScope), scope = _a.scope, resolveLang = _a.resolveLang; /** @type {?} */ var translation = this.translations.get(resolveLang) || {}; return this.getObjectByKey(translation, scope); } } return this.translations; }; /** * Gets an object of translations for a given language * * @example * * selectTranslation().subscribe() - will return the current lang translation * selectTranslation('es').subscribe() * selectTranslation('admin-page').subscribe() - will return the current lang scope translation * selectTranslation('admin-page/es').subscribe() */ /** * Gets an object of translations for a given language * * \@example * * selectTranslation().subscribe() - will return the current lang translation * selectTranslation('es').subscribe() * selectTranslation('admin-page').subscribe() - will return the current lang scope translation * selectTranslation('admin-page/es').subscribe() * @param {?=} lang * @return {?} */ TranslocoService.prototype.selectTranslation = /** * Gets an object of translations for a given language * * \@example * * selectTranslation().subscribe() - will return the current lang translation * selectTranslation('es').subscribe() * selectTranslation('admin-page').subscribe() - will return the current lang scope translation * selectTranslation('admin-page/es').subscribe() * @param {?=} lang * @return {?} */ function (lang) { var _this = this; /** @type {?} */ var language$ = this.langChanges$; if (lang) { /** @type {?} */ var scopeLangSpecified = getLangFromScope(lang) !== lang; if (this.isLang(lang) || scopeLangSpecified) { language$ = of(lang); } else { language$ = this.langChanges$.pipe(map((/** * @param {?} currentLang * @return {?} */ function (currentLang) { return lang + "/" + currentLang; }))); } } return language$.pipe(switchMap((/** * @param {?} language * @return {?} */ function (language) { return _this.load(language).pipe(map((/** * @return {?} */ function () { return _this.getTranslation(language); }))); }))); }; /** * Sets or merge a given translation object to current lang * * @example * * setTranslation({ ... }) * setTranslation({ ... }, 'en') * setTranslation({ ... }, 'es', { merge: false } ) * setTranslation({ ... }, 'todos/en', { merge: false } ) */ /** * Sets or merge a given translation object to current lang * * \@example * * setTranslation({ ... }) * setTranslation({ ... }, 'en') * setTranslation({ ... }, 'es', { merge: false } ) * setTranslation({ ... }, 'todos/en', { merge: false } ) * @param {?} translation * @param {?=} lang * @param {?=} options * @return {?} */ TranslocoService.prototype.setTranslation = /** * Sets or merge a given translation object to current lang * * \@example * * setTranslation({ ... }) * setTranslation({ ... }, 'en') * setTranslation({ ... }, 'es', { merge: false } ) * setTranslation({ ... }, 'todos/en', { merge: false } ) * @param {?} translation * @param {?=} lang * @param {?=} options * @return {?} */ function (translation, lang, options) { if (lang === void 0) { lang = this.getActiveLang(); } if (options === void 0) { options = {}; } var _a; /** @type {?} */ var defaults = { merge: true, emitChange: true }; /** @type {?} */ var mergedOptions = tslib_1.__assign({}, defaults, options); /** @type {?} */ var scope = getScopeFromLang(lang); /** * If this isn't a scope we use the whole translation as is * otherwise we need to flat the scope and use it * @type {?} */ var flattenScopeOrTranslation = translation; // Merged the scoped language into the active language if (scope) { /** @type {?} */ var key = this.getMappedScope(scope); flattenScopeOrTranslation = flatten((_a = {}, _a[key] = translation, _a)); } /** @type {?} */ var currentLang = scope ? getLangFromScope(lang) : lang; /** @type {?} */ var mergedTranslation = tslib_1.__assign({}, (mergedOptions.merge && this.getTranslation(currentLang)), flattenScopeOrTranslation); /** @type {?} */ var flattenTranslation = this.mergedConfig.flatten.aot ? mergedTranslation : flatten(mergedTranslation); /** @type {?} */ var withHook = this.interceptor.preSaveTranslation(flattenTranslation, currentLang); this.translations.set(currentLang, withHook); mergedOptions.emitChange && this.setActiveLang(this.getActiveLang()); }; /** * Sets translation key with given value * * @example * * setTranslationKey('key', 'value') * setTranslationKey('key.nested', 'value') * setTranslationKey('key.nested', 'value', 'en') * setTranslationKey('key.nested', 'value', 'en', { emitChange: false } ) */ /** * Sets translation key with given value * * \@example * * setTranslationKey('key', 'value') * setTranslationKey('key.nested', 'value') * setTranslationKey('key.nested', 'value', 'en') * setTranslationKey('key.nested', 'value', 'en', { emitChange: false } ) * @param {?} key * @param {?} value * @param {?=} lang * @param {?=} options * @return {?} */ TranslocoService.prototype.setTranslationKey = /** * Sets translation key with given value * * \@example * * setTranslationKey('key', 'value') * setTranslationKey('key.nested', 'value') * setTranslationKey('key.nested', 'value', 'en') * setTranslationKey('key.nested', 'value', 'en', { emitChange: false } ) * @param {?} key * @param {?} value * @param {?=} lang * @param {?=} options * @return {?} */ function (key, value, lang, // Todo: Use Omit and merge options and lang to one object in v3 options) { if (lang === void 0) { lang = this.getActiveLang(); } if (options === void 0) { options = {}; } var _a; /** @type {?} */ var withHook = this.interceptor.preSaveTranslationKey(key, value, lang); /** @type {?} */ var newValue = (_a = {}, _a[key] = withHook, _a); this.setTranslation(newValue, lang, tslib_1.__assign({}, options, { merge: true })); }; /** * Sets the fallback lang for the currently active language * @param fallbackLang */ /** * Sets the fallback lang for the currently active language * @param {?} __0 * @return {?} */ TranslocoService.prototype.setFallbackLangForMissingTranslation = /** * Sets the fallback lang for the currently active language * @param {?} __0 * @return {?} */ function (_a) { var fallbackLang = _a.fallbackLang; /** @type {?} */ var lang = Array.isArray(fallbackLang) ? fallbackLang[0] : fallbackLang; if (this.useFallbackTranslation(lang) && fallbackLang) { this.firstFallbackLang = lang; } }; /** * @internal */ /** * \@internal * @param {?} key * @param {?} value * @param {?=} params * @return {?} */ TranslocoService.prototype._handleMissingKey = /** * \@internal * @param {?} key * @param {?} value * @param {?=} params * @return {?} */ function (key, value, params) { if (this.config.missingHandler.allowEmpty && value === '') { return ''; } if (this.useFallbackTranslation() && !this.isResolvedMissingOnce) { // We need to set it to true to prevent a loop this.isResolvedMissingOnce = true; /** @type {?} */ var fallbackValue = this.translate(key, params, this.firstFallbackLang); this.isResolvedMissingOnce = false; return fallbackValue; } return this.missingHandler.handle(key, this.getMissingHandlerData(), params); }; /** * @internal */ /** * \@internal * @param {?} lang * @return {?} */ TranslocoService.prototype._isLangScoped = /** * \@internal * @param {?} lang * @return {?} */ function (lang) { return this.getAvailableLangsIds().indexOf(lang) === -1; }; /** * Checks if a given string is one of the specified available languages. * @returns * True if the given string is an available language. * False if the given string is not an available language. */ /** * Checks if a given string is one of the specified available languages. * @param {?} lang * @return {?} * True if the given string is an available language. * False if the given string is not an available language. */ TranslocoService.prototype.isLang = /** * Checks if a given string is one of the specified available languages. * @param {?} lang * @return {?} * True if the given string is an available language. * False if the given string is not an available language. */ function (lang) { return this.getAvailableLangsIds().indexOf(lang) !== -1; }; /** * @internal * * We always want to make sure the global lang is loaded * before loading the scope since you can access both via the pipe/directive. */ /** * \@internal * * We always want to make sure the global lang is loaded * before loading the scope since you can access both via the pipe/directive. * @param {?} path * @param {?=} inlineLoader * @return {?} */ TranslocoService.prototype._loadDependencies = /** * \@internal * * We always want to make sure the global lang is loaded * before loading the scope since you can access both via the pipe/directive. * @param {?} path * @param {?=} inlineLoader * @return {?} */ function (path, inlineLoader) { /** @type {?} */ var mainLang = getLangFromScope(path); if (this._isLangScoped(path) && !this.isLoadedTranslation(mainLang)) { return combineLatest(this.load(mainLang), this.load(path, { inlineLoader: inlineLoader })); } return this.load(path, { inlineLoader: inlineLoader }); }; /** * @internal */ /** * \@internal * @param {?} langOrScope * @return {?} */ TranslocoService.prototype._completeScopeWithLang = /** * \@internal * @param {?} langOrScope * @return {?} */ function (langOrScope) { if (this._isLangScoped(langOrScope) && !this.isLang(getLangFromScope(langOrScope))) { return langOrScope + "/" + this.getActiveLang(); } return langOrScope; }; /** * @internal */ /** * \@internal * @param {?} scope * @param {?} alias * @return {?} */ TranslocoService.prototype._setScopeAlias = /** * \@internal * @param {?} scope * @param {?} alias * @return {?} */ function (scope, alias) { if (!this.mergedConfig.scopeMapping) { this.mergedConfig.scopeMapping = {}; } this.mergedConfig.scopeMapping[scope] = alias; }; /** * @return {?} */ TranslocoService.prototype.ngOnDestroy = /** * @return {?} */ function () { this.subscription.unsubscribe(); // Caretaker note: since this is the root provider, it'll be destroyed when the `NgModuleRef.destroy()` is run. // Cached values capture `this`, thus leading to a circular reference and preventing the `TranslocoService` from // being GC'd. This would lead to a memory leak when server-side rendering is used since the service is created // and destroyed per each HTTP request, but any service is not getting GC'd. this.cache.clear(); }; /** * @private * @param {?} lang * @return {?} */ TranslocoService.prototype.isLoadedTranslation = /** * @private * @param {?} lang * @return {?} */ function (lang) { return size(this.getTranslation(lang)); }; /** * @private * @return {?} */ TranslocoService.prototype.getAvailableLangsIds = /** * @private * @return {?} */ function () { /** @type {?} */ var first = this.getAvailableLangs()[0]; if (isString(first)) { return (/** @type {?} */ (this.getAvailableLangs())); } return ((/** @type {?} */ (this.getAvailableLangs()))).map((/** * @param {?} l * @return {?} */ function (l) { return l.id; })); }; /** * @private * @return {?} */ TranslocoService.prototype.getMissingHandlerData = /** * @private * @return {?} */ function () { return tslib_1.__assign({}, this.config, { activeLang: this.getActiveLang(), availableLangs: this.availableLangs, defaultLang: this.defaultLang }); }; /** * Use a fallback translation set for missing keys of the primary language * This is unrelated to the fallback language (which changes the active language) */ /** * Use a fallback translation set for missing keys of the primary language * This is unrelated to the fallback language (which changes the active language) * @private * @param {?=} lang * @return {?} */ TranslocoService.prototype.useFallbackTranslation = /** * Use a fallback translation set for missing keys of the primary language * This is unrelated to the fallback language (which changes the active language) * @private * @param {?=} lang * @return {?} */ function (lang) { return this.config.missingHandler.useFallbackTranslation && lang !== this.firstFallbackLang; }; /** * @private * @param {?} lang * @param {?} translation * @return {?} */ TranslocoService.prototype.handleSuccess = /** * @private * @param {?} lang * @param {?} translation * @return {?} */ function (lang, translation) { var _this = this; this.setTranslation(translation, lang, { emitChange: false }); this.events.next({ wasFailure: !!this.failedLangs.size, type: 'translationLoadSuccess', payload: getEventPayload(lang) }); this.failedLangs.forEach((/** * @param {?} l * @return {?} */ function (l) { return _this.cache.delete(l); })); this.failedLangs.clear(); }; /** * @private * @param {?} lang * @param {?} loadOptions * @return {?} */ TranslocoService.prototype.handleFailure = /** * @private * @param {?} lang * @param {?} loadOptions * @return {?} */ function (lang, loadOptions) { // When starting to load a first choice language, initialize // the failed counter and resolve the fallback langs. if (isNil(loadOptions.failedCounter)) { loadOptions.failedCounter = 0; if (!loadOptions.fallbackLangs) { loadOptions.fallbackLangs = this.fallbackStrategy.getNextLangs(lang); } } /** @type {?} */ var splitted = lang.split('/'); /** @type {?} */ var fallbacks = loadOptions.fallbackLangs; /** @type {?} */ var nextLang = fallbacks[loadOptions.failedCounter]; this.failedLangs.add(lang); // This handles the case where a loaded fallback language is requested again if (this.cache.has(nextLang)) { this.handleSuccess(nextLang, this.getTranslation(nextLang)); return EMPTY; } /** @type {?} */ var isFallbackLang = nextLang === splitted[splitted.length - 1]; if (!nextLang || isFallbackLang) { /** @type {?} */ var msg = "Unable to load translation and all the fallback languages"; if (splitted.length > 1) { msg += ", did you misspelled the scope name?"; } throw new Error(msg); } /** @type {?} */ var resolveLang = nextLang; // if it's scoped lang if (splitted.length > 1) { // We need to resolve it to: // todos/langNotExists => todos/nextLang splitted[splitted.length - 1] = nextLang; resolveLang = splitted.join('/'); } loadOptions.failedCounter++; this.events.next({ type: 'translationLoadFailure', payload: getEventPayload(lang) }); return this.load(resolveLang, loadOptions); }; /** * @private * @param {?} scope * @return {?} */ TranslocoService.prototype.getMappedScope = /** * @private * @param {?} scope * @return {?} */ function (scope) { var _a = this.config.scopeMapping, scopeMapping = _a === void 0 ? {} : _a; return scopeMapping[scope] || toCamelCase(scope); }; /** * If lang is scope we need to check the following cases: * todos/es => in this case we should take `es` as lang * todos => in this case we should set the active lang as lang */ /** * If lang is scope we need to check the following cases: * todos/es => in this case we should take `es` as lang * todos => in this case we should set the active lang as lang * @private * @param {?} lang * @return {?} */ TranslocoService.prototype.resolveLangAndScope = /** * If lang is scope we need to check the following cases: * todos/es => in this case we should take `es` as lang * todos => in this case we should set the active lang as lang * @private * @param {?} lang * @return {?} */ function (lang) { /** @type {?} */ var resolveLang = lang; /** @type {?} */ var scope; if (this._isLangScoped(lang)) { // en for example /** @type {?} */ var langFromScope = getLangFromScope(lang); // en is lang /** @type {?} */ var hasLang = this.isLang(langFromScope); // take en resolveLang = hasLang ? langFromScope : this.getActiveLang(); // find the scope scope = this.getMappedScope(hasLang ? getScopeFromLang(lang) : lang); } return { scope: scope, resolveLang: resolveLang }; }; /** * @private * @param {?} translation * @param {?} key * @return {?} */ TranslocoService.prototype.getObjectByKey = /** * @private * @param {?} translation * @param {?} key * @return {?} */ function (translation, key) { /** @type {?} */ var result = {}; /** @type {?} */ var prefix = key + "."; for (var currentKey in translation) { if (currentKey.startsWith(prefix)) { result[currentKey.replace(prefix, '')] = translation[currentKey]; } } return result; }; /** * @private * @param {?} key * @return {?} */ TranslocoService.prototype.getEntries = /** * @private * @param {?} key * @return {?} */ function (key) { return key instanceof Map ? key.entries() : Object.entries(key); }; TranslocoService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ TranslocoService.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [TRANSLOCO_LOADER,] }] }, { type: undefined, decorators: [{ type: Inject, args: [TRANSLOCO_TRANSPILER,] }] }, { type: undefined, decorators: [{ type: Inject, args: [TRANSLOCO_MISSING_HANDLER,] }] }, { type: undefined, decorators: [{ type: Inject, args: [TRANSLOCO_INTERCEPTOR,] }] }, { type: undefined, decorators: [{ type: Inject, args: [TRANSLOCO_CONFIG,] }] }, { type: undefined, decorators: [{ type: Inject, args: [TRANSLOCO_FALLBACK_STRATEGY,] }] } ]; }; /** @nocollapse */ TranslocoService.ngInjectableDef = i0.defineInjectable({ factory: function TranslocoService_Factory() { return new TranslocoService(i0.inject(i1.TRANSLOCO_LOADER, 8), i0.inject(i2.TRANSLOCO_TRANSPILER), i0.inject(i3.TRANSLOCO_MISSING_HANDLER), i0.inject(i4.TRANSLOCO_INTERCEPTOR), i0.inject(i5.TRANSLOCO_CONFIG), i0.inject(i6.TRANSLOCO_FALLBACK_STRATEGY)); }, token: TranslocoService, providedIn: "root" }); return TranslocoService; }()); export { TranslocoService }; if (false) { /** * @type {?} * @private */ TranslocoService.prototype.subscription; /** * @type {?} * @private */ TranslocoService.prototype.translations; /** * @type {?} * @private */ TranslocoService.prototype.cache; /** * @type {?} * @private */ TranslocoService.prototype.firstFallbackLang; /** * @type {?} * @private */ TranslocoService.prototype.defaultLang; /** * @type {?} * @private */ TranslocoService.prototype.mergedConfig; /** * @type {?} * @private */ TranslocoService.prototype.availableLangs; /** * @type {?} * @private */ TranslocoService.prototype.isResolvedMissingOnce; /** * @type {?} * @private */ TranslocoService.prototype.lang; /** @type {?} */ TranslocoService.prototype.langChanges$; /** * @type {?} * @private */ TranslocoService.prototype.events; /** @type {?} */ TranslocoService.prototype.events$; /** * @type {?} * @private */ TranslocoService.prototype.failedLangs; /** * @type {?} * @private */ TranslocoService.prototype.loader; /** * @type {?} * @private */ TranslocoService.prototype.parser; /** * @type {?} * @private */ TranslocoService.prototype.missingHandler; /** * @type {?} * @private */ TranslocoService.prototype.interceptor; /** * @type {?} * @private */ TranslocoService.prototype.userConfig; /** * @type {?} * @private */ TranslocoService.prototype.fallbackStrategy; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsb2NvLnNlcnZpY2UuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AbmduZWF0L3RyYW5zbG9jby8iLCJzb3VyY2VzIjpbImxpYi90cmFuc2xvY28uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBYSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDeEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQWMsRUFBRSxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDcEgsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckYsT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBbUIsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RixPQUFPLEVBQUUsb0JBQW9CLEVBQXVCLE1BQU0sd0JBQXdCLENBQUM7QUFjbkYsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDM0csT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBbUIsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RixPQUFPLEVBQ0wseUJBQXlCLEVBRzFCLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUFFLHFCQUFxQixFQUF3QixNQUFNLHlCQUF5QixDQUFDO0FBQ3RGLE9BQU8sRUFBRSwyQkFBMkIsRUFBNkIsTUFBTSwrQkFBK0IsQ0FBQztBQUN2RyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0Is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