UNPKG

@ngneat/transloco

Version:

The internationalization (i18n) library for Angular

876 lines 82.6 kB
/** * @fileoverview added by tsickle * Generated from: lib/transloco.service.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ 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 {?} */ let service; /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ export function translate(key, params = {}, lang) { return service.translate(key, params, lang); } export class TranslocoService { /** * @param {?} loader * @param {?} parser * @param {?} missingHandler * @param {?} interceptor * @param {?} userConfig * @param {?} fallbackStrategy */ constructor(loader, parser, missingHandler, interceptor, userConfig, fallbackStrategy) { 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 {?} */ e => { if (e.type === 'translationLoadSuccess' && e.wasFailure) { // Handle scoped lang /** @type {?} */ const lang = getLangFromScope(e.payload.lang); this.setActiveLang(lang); } })); } /** * @return {?} */ get config() { return this.mergedConfig; } /** * @return {?} */ getDefaultLang() { return this.defaultLang; } /** * @param {?} lang * @return {?} */ setDefaultLang(lang) { this.defaultLang = lang; } /** * @return {?} */ getActiveLang() { return this.lang.getValue(); } /** * @template THIS * @this {THIS} * @param {?} lang * @return {THIS} */ setActiveLang(lang) { (/** @type {?} */ (this)).parser.onLangChanged && (/** @type {?} */ (this)).parser.onLangChanged(lang); (/** @type {?} */ (this)).lang.next(lang); return (/** @type {?} */ (this)); } /** * @param {?} langs * @return {?} */ setAvailableLangs(langs) { this.availableLangs = langs; } /** * 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. */ getAvailableLangs() { return this.availableLangs; } /** * @param {?} path * @param {?=} options * @return {?} */ load(path, options = {}) { if (this.cache.has(path) === false) { /** @type {?} */ let loadTranslation; /** @type {?} */ const isScope = this._isLangScoped(path); /** @type {?} */ const scope = isScope ? getScopeFromLang(path) : null; if (this.useFallbackTranslation(path)) { // if the path is scope the fallback should be `scope/fallbackLang`; /** @type {?} */ const fallback = isScope ? `${scope}/${this.firstFallbackLang}` : this.firstFallbackLang; /** @type {?} */ const loaders = getFallbacksLoaders(path, fallback, this.loader, options.inlineLoader, { scope }); loadTranslation = forkJoin(loaders); } else { /** @type {?} */ const loader = resolveLoader(path, this.loader, options.inlineLoader, { scope }); loadTranslation = from(loader); } /** @type {?} */ const load$ = loadTranslation.pipe(retry(this.config.failedRetries), tap((/** * @param {?} translation * @return {?} */ translation => { if (Array.isArray(translation)) { translation.forEach((/** * @param {?} t * @return {?} */ 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 {?} */ () => 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') * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ translate(key, params = {}, lang = this.getActiveLang()) { if (!key) return (/** @type {?} */ (key)); const { scope, resolveLang } = this.resolveLangAndScope(lang); if (Array.isArray(key)) { return (/** @type {?} */ (key.map((/** * @param {?} k * @return {?} */ k => this.translate(scope ? `${scope}.${k}` : k, params, resolveLang))))); } key = scope ? `${scope}.${key}` : key; /** @type {?} */ const translation = this.getTranslation(resolveLang); /** @type {?} */ const 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 => ...) * * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @param {?=} _isObject * @return {?} */ selectTranslate(key, params, lang, _isObject = false) { /** @type {?} */ let inlineLoader = null; /** @type {?} */ const load = (/** * @param {?} lang * @param {?=} options * @return {?} */ (lang, options) => this.load(lang, options).pipe(map((/** * @return {?} */ () => (_isObject ? this.translateObject(key, params, lang) : this.translate(key, params, lang)))))); if (isNil(lang)) { return this.langChanges$.pipe(switchMap((/** * @param {?} lang * @return {?} */ lang => load(lang)))); } if (isScopeObject(lang)) { // it's a scope object. /** @type {?} */ const 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 {?} */ const scope = lang; return this.langChanges$.pipe(switchMap((/** * @param {?} lang * @return {?} */ lang => load(`${scope}/${lang}`, { inlineLoader })))); } /** * Whether the scope with lang * * \@example * * todos/en => true * todos => false * @private * @param {?} lang * @return {?} */ isScopeWithLang(lang) { return this.isLang(getLangFromScope(lang)); } /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ translateObject(key, params, lang = this.getActiveLang()) { if (isString(key) || Array.isArray(key)) { if (Array.isArray(key)) { return (/** @type {?} */ (key.map((/** * @param {?} k * @return {?} */ k => this.translateObject(scope ? `${scope}.${k}` : k, params, resolveLang))))); } const { resolveLang, scope } = this.resolveLangAndScope(lang); /** @type {?} */ const translation = this.getTranslation(resolveLang); key = scope ? `${scope}.${key}` : key; /** @type {?} */ const 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 {?} */ const translations = []; for (const [_key, _params] of this.getEntries(key)) { translations.push(this.translateObject(_key, _params, lang)); } return translations; } /** * @template T * @param {?} key * @param {?=} params * @param {?=} lang * @return {?} */ selectTranslateObject(key, params, lang) { if (isString(key) || Array.isArray(key)) { return this.selectTranslate(key, params, lang, true); } const [[firstKey, firstParams], ...rest] = this.getEntries(key); /* 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 {?} */ value => { /** @type {?} */ const translations = [value]; for (const [_key, _params] of rest) { translations.push(this.translateObject(_key, _params, lang)); } return translations; }))); } /** * @param {?=} langOrScope * @return {?} */ getTranslation(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 const { scope, resolveLang } = this.resolveLangAndScope(langOrScope); /** @type {?} */ const 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() * @param {?=} lang * @return {?} */ selectTranslation(lang) { /** @type {?} */ let language$ = this.langChanges$; if (lang) { /** @type {?} */ const scopeLangSpecified = getLangFromScope(lang) !== lang; if (this.isLang(lang) || scopeLangSpecified) { language$ = of(lang); } else { language$ = this.langChanges$.pipe(map((/** * @param {?} currentLang * @return {?} */ currentLang => `${lang}/${currentLang}`))); } } return language$.pipe(switchMap((/** * @param {?} language * @return {?} */ language => this.load(language).pipe(map((/** * @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 } ) * @param {?} translation * @param {?=} lang * @param {?=} options * @return {?} */ setTranslation(translation, lang = this.getActiveLang(), options = {}) { /** @type {?} */ const defaults = { merge: true, emitChange: true }; /** @type {?} */ const mergedOptions = Object.assign({}, defaults, options); /** @type {?} */ const 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 {?} */ let flattenScopeOrTranslation = translation; // Merged the scoped language into the active language if (scope) { /** @type {?} */ const key = this.getMappedScope(scope); flattenScopeOrTranslation = flatten({ [key]: translation }); } /** @type {?} */ const currentLang = scope ? getLangFromScope(lang) : lang; /** @type {?} */ const mergedTranslation = Object.assign({}, (mergedOptions.merge && this.getTranslation(currentLang)), flattenScopeOrTranslation); /** @type {?} */ const flattenTranslation = this.mergedConfig.flatten.aot ? mergedTranslation : flatten(mergedTranslation); /** @type {?} */ const 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 } ) * @param {?} key * @param {?} value * @param {?=} lang * @param {?=} options * @return {?} */ setTranslationKey(key, value, lang = this.getActiveLang(), // Todo: Use Omit and merge options and lang to one object in v3 options = {}) { /** @type {?} */ const withHook = this.interceptor.preSaveTranslationKey(key, value, lang); /** @type {?} */ const newValue = { [key]: withHook }; this.setTranslation(newValue, lang, Object.assign({}, options, { merge: true })); } /** * Sets the fallback lang for the currently active language * @param {?} __0 * @return {?} */ setFallbackLangForMissingTranslation({ fallbackLang }) { /** @type {?} */ const lang = Array.isArray(fallbackLang) ? fallbackLang[0] : fallbackLang; if (this.useFallbackTranslation(lang) && fallbackLang) { this.firstFallbackLang = lang; } } /** * \@internal * @param {?} key * @param {?} value * @param {?=} params * @return {?} */ _handleMissingKey(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 {?} */ const fallbackValue = this.translate(key, params, this.firstFallbackLang); this.isResolvedMissingOnce = false; return fallbackValue; } return this.missingHandler.handle(key, this.getMissingHandlerData(), params); } /** * \@internal * @param {?} lang * @return {?} */ _isLangScoped(lang) { return this.getAvailableLangsIds().indexOf(lang) === -1; } /** * 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. */ isLang(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. * @param {?} path * @param {?=} inlineLoader * @return {?} */ _loadDependencies(path, inlineLoader) { /** @type {?} */ const mainLang = getLangFromScope(path); if (this._isLangScoped(path) && !this.isLoadedTranslation(mainLang)) { return combineLatest(this.load(mainLang), this.load(path, { inlineLoader })); } return this.load(path, { inlineLoader }); } /** * \@internal * @param {?} langOrScope * @return {?} */ _completeScopeWithLang(langOrScope) { if (this._isLangScoped(langOrScope) && !this.isLang(getLangFromScope(langOrScope))) { return `${langOrScope}/${this.getActiveLang()}`; } return langOrScope; } /** * \@internal * @param {?} scope * @param {?} alias * @return {?} */ _setScopeAlias(scope, alias) { if (!this.mergedConfig.scopeMapping) { this.mergedConfig.scopeMapping = {}; } this.mergedConfig.scopeMapping[scope] = alias; } /** * @return {?} */ ngOnDestroy() { 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 {?} */ isLoadedTranslation(lang) { return size(this.getTranslation(lang)); } /** * @private * @return {?} */ getAvailableLangsIds() { /** @type {?} */ const first = this.getAvailableLangs()[0]; if (isString(first)) { return (/** @type {?} */ (this.getAvailableLangs())); } return ((/** @type {?} */ (this.getAvailableLangs()))).map((/** * @param {?} l * @return {?} */ l => l.id)); } /** * @private * @return {?} */ getMissingHandlerData() { return Object.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) * @private * @param {?=} lang * @return {?} */ useFallbackTranslation(lang) { return this.config.missingHandler.useFallbackTranslation && lang !== this.firstFallbackLang; } /** * @private * @param {?} lang * @param {?} translation * @return {?} */ handleSuccess(lang, translation) { this.setTranslation(translation, lang, { emitChange: false }); this.events.next({ wasFailure: !!this.failedLangs.size, type: 'translationLoadSuccess', payload: getEventPayload(lang) }); this.failedLangs.forEach((/** * @param {?} l * @return {?} */ l => this.cache.delete(l))); this.failedLangs.clear(); } /** * @private * @param {?} lang * @param {?} loadOptions * @return {?} */ handleFailure(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 {?} */ const splitted = lang.split('/'); /** @type {?} */ const fallbacks = loadOptions.fallbackLangs; /** @type {?} */ const 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 {?} */ const isFallbackLang = nextLang === splitted[splitted.length - 1]; if (!nextLang || isFallbackLang) { /** @type {?} */ let 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 {?} */ let 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 {?} */ getMappedScope(scope) { const { scopeMapping = {} } = this.config; 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 * @private * @param {?} lang * @return {?} */ resolveLangAndScope(lang) { /** @type {?} */ let resolveLang = lang; /** @type {?} */ let scope; if (this._isLangScoped(lang)) { // en for example /** @type {?} */ const langFromScope = getLangFromScope(lang); // en is lang /** @type {?} */ const hasLang = this.isLang(langFromScope); // take en resolveLang = hasLang ? langFromScope : this.getActiveLang(); // find the scope scope = this.getMappedScope(hasLang ? getScopeFromLang(lang) : lang); } return { scope, resolveLang }; } /** * @private * @param {?} translation * @param {?} key * @return {?} */ getObjectByKey(translation, key) { /** @type {?} */ const result = {}; /** @type {?} */ const prefix = `${key}.`; for (const currentKey in translation) { if (currentKey.startsWith(prefix)) { result[currentKey.replace(prefix, '')] = translation[currentKey]; } } return result; } /** * @private * @param {?} key * @return {?} */ getEntries(key) { return key instanceof Map ? key.entries() : Object.entries(key); } } TranslocoService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ TranslocoService.ctorParameters = () => [ { 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" }); 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsb2NvLnNlcnZpY2UuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AbmduZWF0L3RyYW5zbG9jby8iLCJzb3VyY2VzIjpbImxpYi90cmFuc2xvY28uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFhLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RSxPQUFPLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBYyxFQUFFLEVBQUUsT0FBTyxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUNwSCxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRixPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFtQixNQUFNLG9CQUFvQixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxvQkFBb0IsRUFBdUIsTUFBTSx3QkFBd0IsQ0FBQztBQWNuRixPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUMzRyxPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFtQixNQUFNLG9CQUFvQixDQUFDO0FBQ3RGLE9BQU8sRUFDTCx5QkFBeUIsRUFHMUIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUscUJBQXFCLEVBQXdCLE1BQU0seUJBQXlCLENBQUM7QUFDdEYsT0FBTyxFQUFFLDJCQUEyQixFQUE2QixNQUFNLCtCQUErQixDQUFDO0FBQ3ZHLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixF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