@ngneat/transloco
Version:
The internationalization (i18n) library for Angular
1,262 lines • 96.3 kB
JavaScript
/**
* @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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsb2NvLnNlcnZpY2UuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AbmduZWF0L3RyYW5zbG9jby8iLCJzb3VyY2VzIjpbImxpYi90cmFuc2xvY28uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBYSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDeEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQWMsRUFBRSxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDcEgsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckYsT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBbUIsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RixPQUFPLEVBQUUsb0JBQW9CLEVBQXVCLE1BQU0sd0JBQXdCLENBQUM7QUFjbkYsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDM0csT0FBTyxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBbUIsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RixPQUFPLEVBQ0wseUJBQXlCLEVBRzFCLE1BQU0sNkJBQTZCLENBQUM7QUFDckMsT0FBTyxFQUFFLHFCQUFxQixFQUF3QixNQUFNLHlCQUF5QixDQUFDO0FBQ3RGLE9BQU8sRUFBRSwyQkFBMkIsRUFBNkIsTUFBTSwrQkFBK0IsQ0FBQztBQUN2RyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNwRyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7Ozs7Ozs7OztJQUU3QyxPQUF5Qjs7Ozs7Ozs7QUFFN0IsTUFBTSxVQUFVLFNBQVMsQ0FBVSxHQUFvQixFQUFFLE1BQW9CLEVBQUUsSUFBYTtJQUFuQyx1QkFBQSxFQUFBLFdBQW9CO0lBQzNFLE9BQU8sT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRDtJQWtCRSwwQkFDZ0QsTUFBdUIsRUFDL0IsTUFBMkIsRUFDdEIsY0FBdUMsRUFDM0MsV0FBaUMsRUFDdEMsVUFBMkIsRUFDaEIsZ0JBQTJDO1FBTjFGLGlCQWdDQztRQS9CK0MsV0FBTSxHQUFOLE1BQU0sQ0FBaUI7UUFDL0IsV0FBTSxHQUFOLE1BQU0sQ0FBcUI7UUFDdEIsbUJBQWMsR0FBZCxjQUFjLENBQXlCO1FBQzNDLGdCQUFXLEdBQVgsV0FBVyxDQUFzQjtRQUN0QyxlQUFVLEdBQVYsVUFBVSxDQUFpQjtRQUNoQixxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQTJCO1FBckJsRixpQkFBWSxHQUFHLElBQUksR0FBRyxFQUF1QixDQUFDO1FBQzlDLFVBQUssR0FBRyxJQUFJLEdBQUcsRUFBbUMsQ0FBQztRQUNuRCxzQkFBaUIsR0FBa0IsSUFBSSxDQUFDO1FBR3hDLG1CQUFjLEdBQW1CLEVBQUUsQ0FBQztRQUNwQywwQkFBcUIsR0FBRyxLQUFLLENBQUM7UUFJOUIsV0FBTSxHQUFHLElBQUksT0FBTyxFQUFtQixDQUFDO1FBQ2hELFlBQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBRTdCLGdCQUFXLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQVV0QyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNoQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztTQUNwRDtRQUNELE9BQU8sR0FBRyxJQUFJLENBQUM7UUFDZixJQUFJLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQyxhQUFhLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFM0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLG9DQUFvQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM3RCxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDbkQsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLGVBQWUsQ0FBUyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUMvRCxrRUFBa0U7UUFDbEUsNERBQTREO1FBQzVELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUU3Qzs7V0FFRztRQUNILElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTOzs7O1FBQUMsVUFBQSxDQUFDO1lBQzFDLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyx3QkFBd0IsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFOzs7b0JBRWpELElBQUksR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDN0MsS0FBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUMxQjtRQUNILENBQUMsRUFBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELHNCQUFJLG9DQUFNOzs7O1FBQVY7WUFDRSxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7UUFDM0IsQ0FBQzs7O09BQUE7Ozs7SUFFRCx5Q0FBYzs7O0lBQWQ7UUFDRSxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQzs7Ozs7SUFFRCx5Q0FBYzs7OztJQUFkLFVBQWUsSUFBWTtRQUN6QixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztJQUMxQixDQUFDOzs7O0lBRUQsd0NBQWE7OztJQUFiO1FBQ0UsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQzlCLENBQUM7Ozs7Ozs7SUFFRCx3Q0FBYTs7Ozs7O0lBQWIsVUFBYyxJQUFZO1FBQ3hCLG1CQUFBLElBQUksRUFBQSxDQUFDLE1BQU0sQ0FBQyxhQUFhLElBQUksbUJBQUEsSUFBSSxFQUFBLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3RCxtQkFBQSxJQUFJLEVBQUEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JCLE9BQU8sbUJBQUEsSUFBSSxFQUFBLENBQUM7SUFDZCxDQUFDOzs7OztJQUVELDRDQUFpQjs7OztJQUFqQixVQUFrQixLQUFxQjtRQUNyQyxJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQztJQUM5QixDQUFDO0lBRUQ7Ozs7OztPQU1HOzs7Ozs7OztJQUNILDRDQUFpQjs7Ozs7OztJQUFqQjtRQUNFLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQztJQUM3QixDQUFDOzs7Ozs7SUFFRCwrQkFBSTs7Ozs7SUFBSixVQUFLLElBQVksRUFBRSxPQUF5QjtRQUE1QyxpQkF1Q0M7UUF2Q2tCLHdCQUFBLEVBQUEsWUFBeUI7UUFDMUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLEVBQUU7O2dCQUM5QixlQUFlLFNBQXdFOztnQkFDckYsT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDOztnQkFDbEMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUk7WUFDckQsSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLEVBQUU7OztvQkFFL0IsUUFBUSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUksS0FBSyxTQUFJLElBQUksQ0FBQyxpQkFBbUIsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQjs7b0JBRWxGLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLEtBQUssT0FBQSxFQUFFLENBQUM7Z0JBQ2pHLGVBQWUsR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDckM7aUJBQU07O29CQUNDLE1BQU0sR0FBRyxhQUFhLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLEtBQUssT0FBQSxFQUFFLENBQUM7Z0JBQ2hGLGVBQWUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDaEM7O2dCQUVLLEtBQUssR0FBRyxlQUFlLENBQUMsSUFBSSxDQUNoQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFDaEMsR0FBRzs7OztZQUFDLFVBQUEsV0FBVztnQkFDYixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEVBQUU7b0JBQzlCLFdBQVcsQ0FBQyxPQUFPOzs7O29CQUFDLFVBQUEsQ0FBQzt3QkFDbkIsS0FBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQzt3QkFDMUMscUVBQXFFO3dCQUNyRSxJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxFQUFFOzRCQUNuQixLQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO3lCQUNoQztvQkFDSCxDQUFDLEVBQUMsQ0FBQztvQkFDSCxPQUFPO2lCQUNSO2dCQUNELEtBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3hDLENBQUMsRUFBQyxFQUNGLFVBQVU7OztZQUFDLGNBQU0sT0FBQSxLQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsRUFBakMsQ0FBaUMsRUFBQyxFQUNuRCxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQ2Y7WUFFRCxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDN0I7UUFFRCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHOzs7Ozs7Ozs7Ozs7Ozs7OztJQUNILG9DQUFTOzs7Ozs7Ozs7Ozs7Ozs7O0lBQVQsVUFBbUIsR0FBb0IsRUFBRSxNQUFvQixFQUFFLElBQTJCO1FBQTFGLGlCQW1CQztRQW5Cd0MsdUJBQUEsRUFBQSxXQUFvQjtRQUFFLHFCQUFBLEVBQUEsT0FBTyxJQUFJLENBQUMsYUFBYSxFQUFFO1FBQ3hGLElBQUksQ0FBQyxHQUFHO1lBQUUsT0FBTyxtQkFBQSxHQUFHLEVBQU8sQ0FBQztRQUV0QixJQUFBLG1DQUF1RCxFQUFyRCxnQkFBSyxFQUFFLDRCQUE4QztRQUU3RCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDdEIsT0FBTyxtQkFBQSxHQUFHLENBQUMsR0FBRzs7OztZQUFDLFVBQUEsQ0FBQyxJQUFJLE9BQUEsS0FBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFJLEtBQUssU0FBSSxDQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLEVBQWhFLENBQWdFLEVBQUMsRUFBTyxDQUFDO1NBQzlGO1FBRUQsR0FBRyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUksS0FBSyxTQUFJLEdBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDOztZQUVoQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUM7O1lBQzlDLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDO1FBRTlCLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDVixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ25EO1FBRUQsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRDs7Ozs7Ozs7OztPQVVHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7SUFDSCwwQ0FBZTs7Ozs7Ozs7Ozs7Ozs7Ozs7SUFBZixVQUNFLEdBQW9CLEVBQ3BCLE1BQWdCLEVBQ2hCLElBQThCLEVBQzlCLFNBQWlCO1FBSm5CLGlCQTZCQztRQXpCQywwQkFBQSxFQUFBLGlCQUFpQjs7WUFFYixZQUFZLEdBQUcsSUFBSTs7WUFDakIsSUFBSTs7Ozs7UUFBRyxVQUFDLElBQUksRUFBRSxPQUFxQjtZQUN2QyxPQUFBLEtBQUksQ