UNPKG

angular-l10n

Version:

Angular library to translate texts, dates and numbers

152 lines 23.9 kB
import { Injectable, Inject } from '@angular/core'; import { L10N_CONFIG, L10N_LOCALE } from '../models/l10n-config'; import { toDate, toNumber, PARSE_DATE_STYLE, PARSE_TIME_STYLE, parseDigits } from '../models/utils'; import * as i0 from "@angular/core"; import * as i1 from "./l10n-translation.service"; export class L10nIntlService { constructor(config, locale, translation) { this.config = config; this.locale = locale; this.translation = translation; } /** * Formats a date. * @param value A date, a number (milliseconds since UTC epoch) or an ISO 8601 string * @param options A L10n or Intl DateTimeFormatOptions object * @param language The current language * @param timeZone The current time zone */ formatDate(value, options, language = this.locale.dateLanguage || this.locale.language, timeZone = this.locale.timeZone) { value = toDate(value); let dateTimeFormatOptions = {}; if (options) { if (options) { const { dateStyle, timeStyle, ...rest } = options; if (dateStyle) { dateTimeFormatOptions = { ...dateTimeFormatOptions, ...PARSE_DATE_STYLE[dateStyle] }; } if (timeStyle) { dateTimeFormatOptions = { ...dateTimeFormatOptions, ...PARSE_TIME_STYLE[timeStyle] }; } dateTimeFormatOptions = { ...dateTimeFormatOptions, ...rest }; } } if (timeZone) { dateTimeFormatOptions.timeZone = timeZone; } return new Intl.DateTimeFormat(language, dateTimeFormatOptions).format(value); } /** * Formats a number. * @param value A number or a string * @param options A L10n or Intl NumberFormatOptions object * @param language The current language * @param currency The current currency * @param convert An optional function to convert the value, with value and locale in the signature. * For example: * ``` * const convert = (value: number, locale: L10nLocale) => { return ... }; * ``` * @param convertParams Optional parameters for the convert function */ formatNumber(value, options, language = this.locale.numberLanguage || this.locale.language, currency = this.locale.currency, convert, convertParams) { if (options && options['style'] === 'unit' && !options['unit']) return value; value = toNumber(value); // Optional conversion. if (typeof convert === 'function') { value = convert(value, this.locale, Object.values(convertParams || {})); // Destructures params } let numberFormatOptions = {}; if (options) { const { digits, ...rest } = options; if (digits) { numberFormatOptions = { ...numberFormatOptions, ...parseDigits(digits) }; } numberFormatOptions = { ...numberFormatOptions, ...rest }; } if (currency) numberFormatOptions.currency = currency; return new Intl.NumberFormat(language, numberFormatOptions).format(value); } /** * Formats a relative time. * @param value A negative (or positive) number * @param unit An Intl RelativeTimeFormatUnit value * @param options An Intl RelativeTimeFormatOptions object * @param language The current language */ formatRelativeTime(value, unit, options, language = this.locale.dateLanguage || this.locale.language) { value = toNumber(value); return new Intl.RelativeTimeFormat(language, options).format(value, unit); } /** * Gets the plural by a number. * The 'value' is passed as a parameter to the translation function. * @param value The number to get the plural * @param prefix Optional prefix for the key * @param options An Intl PluralRulesOptions object * @param language The current language */ plural(value, prefix = '', options, language = this.locale.language) { value = toNumber(value); const rule = new Intl.PluralRules(language, options).select(value); const key = prefix ? `${prefix}${this.config.keySeparator}${rule}` : rule; return this.translation.translate(key, { value }); } /** * Returns translation of language, region, script or currency display names * @param code ISO code of language, region, script or currency * @param options An Intl DisplayNamesOptions object * @param language The current language */ displayNames(code, options, language = this.locale.language) { return new Intl.DisplayNames(language, options).of(code) || code; } getCurrencySymbol(locale = this.locale) { const decimal = this.formatNumber(0, { digits: '1.0-0' }, locale.numberLanguage || locale.language); const currency = this.formatNumber(0, { digits: '1.0-0', style: 'currency', currencyDisplay: 'symbol' }, locale.numberLanguage || locale.language, locale.currency); let symbol = currency.replace(decimal, ''); symbol = symbol.trim(); return symbol; } /** * Compares two keys by the value of translation. * @param key1 First key to compare * @param key1 Second key to compare * @param options An Intl CollatorOptions object * @param language The current language * @return A negative value if the value of translation of key1 comes before the value of translation of key2; * a positive value if key1 comes after key2; * 0 if they are considered equal or Intl.Collator is not supported */ compare(key1, key2, options, language = this.locale.language) { const value1 = this.translation.translate(key1); const value2 = this.translation.translate(key2); return new Intl.Collator(language, options).compare(value1, value2); } /** * Returns the representation of a list. * @param list An array of keys * @param options An Intl ListFormatOptions object * @param language The current language */ list(list, options, language = this.locale.language) { const values = list.map(key => this.translation.translate(key)); if (language == null || language === '') return values.join(', '); return new Intl.ListFormat(language, options).format(values); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: L10nIntlService, deps: [{ token: L10N_CONFIG }, { token: L10N_LOCALE }, { token: i1.L10nTranslationService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: L10nIntlService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.4", ngImport: i0, type: L10nIntlService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [L10N_CONFIG] }] }, { type: undefined, decorators: [{ type: Inject, args: [L10N_LOCALE] }] }, { type: i1.L10nTranslationService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibDEwbi1pbnRsLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWwxMG4vc3JjL2xpYi9zZXJ2aWNlcy9sMTBuLWludGwuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUduRCxPQUFPLEVBQWMsV0FBVyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzdFLE9BQU8sRUFDSCxNQUFNLEVBQ04sUUFBUSxFQUNSLGdCQUFnQixFQUNoQixnQkFBZ0IsRUFDaEIsV0FBVyxFQUNkLE1BQU0saUJBQWlCLENBQUM7OztBQUdYLE1BQU0sT0FBTyxlQUFlO0lBRXRDLFlBQ2lDLE1BQWtCLEVBQ2xCLE1BQWtCLEVBQ3ZDLFdBQW1DO1FBRmQsV0FBTSxHQUFOLE1BQU0sQ0FBWTtRQUNsQixXQUFNLEdBQU4sTUFBTSxDQUFZO1FBQ3ZDLGdCQUFXLEdBQVgsV0FBVyxDQUF3QjtJQUMzQyxDQUFDO0lBRUw7Ozs7OztPQU1HO0lBQ0ksVUFBVSxDQUNiLEtBQVUsRUFDVixPQUFtQyxFQUNuQyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQzNELFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVE7UUFFL0IsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV0QixJQUFJLHFCQUFxQixHQUErQixFQUFFLENBQUM7UUFDM0QsSUFBSSxPQUFPLEVBQUU7WUFDVCxJQUFJLE9BQU8sRUFBRTtnQkFDVCxNQUFNLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxHQUFHLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQztnQkFDbEQsSUFBSSxTQUFTLEVBQUU7b0JBQ1gscUJBQXFCLEdBQUcsRUFB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Q29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBJbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbmltcG9ydCB7IEwxMG5Mb2NhbGUsIEwxMG5EYXRlVGltZUZvcm1hdE9wdGlvbnMsIEwxMG5OdW1iZXJGb3JtYXRPcHRpb25zIH0gZnJvbSAnLi4vbW9kZWxzL3R5cGVzJztcclxuaW1wb3J0IHsgTDEwbkNvbmZpZywgTDEwTl9DT05GSUcsIEwxME5fTE9DQUxFIH0gZnJvbSAnLi4vbW9kZWxzL2wxMG4tY29uZmlnJztcclxuaW1wb3J0IHtcclxuICAgIHRvRGF0ZSxcclxuICAgIHRvTnVtYmVyLFxyXG4gICAgUEFSU0VfREFURV9TVFlMRSxcclxuICAgIFBBUlNFX1RJTUVfU1RZTEUsXHJcbiAgICBwYXJzZURpZ2l0c1xyXG59IGZyb20gJy4uL21vZGVscy91dGlscyc7XHJcbmltcG9ydCB7IEwxMG5UcmFuc2xhdGlvblNlcnZpY2UgfSBmcm9tICcuL2wxMG4tdHJhbnNsYXRpb24uc2VydmljZSc7XHJcblxyXG5ASW5qZWN0YWJsZSgpIGV4cG9ydCBjbGFzcyBMMTBuSW50bFNlcnZpY2Uge1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIEBJbmplY3QoTDEwTl9DT05GSUcpIHByaXZhdGUgY29uZmlnOiBMMTBuQ29uZmlnLFxyXG4gICAgICAgIEBJbmplY3QoTDEwTl9MT0NBTEUpIHByaXZhdGUgbG9jYWxlOiBMMTBuTG9jYWxlLFxyXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRpb246IEwxMG5UcmFuc2xhdGlvblNlcnZpY2VcclxuICAgICkgeyB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGb3JtYXRzIGEgZGF0ZS5cclxuICAgICAqIEBwYXJhbSB2YWx1ZSBBIGRhdGUsIGEgbnVtYmVyIChtaWxsaXNlY29uZHMgc2luY2UgVVRDIGVwb2NoKSBvciBhbiBJU08gODYwMSBzdHJpbmdcclxuICAgICAqIEBwYXJhbSBvcHRpb25zIEEgTDEwbiBvciBJbnRsIERhdGVUaW1lRm9ybWF0T3B0aW9ucyBvYmplY3RcclxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSBUaGUgY3VycmVudCBsYW5ndWFnZVxyXG4gICAgICogQHBhcmFtIHRpbWVab25lIFRoZSBjdXJyZW50IHRpbWUgem9uZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZm9ybWF0RGF0ZShcclxuICAgICAgICB2YWx1ZTogYW55LFxyXG4gICAgICAgIG9wdGlvbnM/OiBMMTBuRGF0ZVRpbWVGb3JtYXRPcHRpb25zLFxyXG4gICAgICAgIGxhbmd1YWdlID0gdGhpcy5sb2NhbGUuZGF0ZUxhbmd1YWdlIHx8IHRoaXMubG9jYWxlLmxhbmd1YWdlLFxyXG4gICAgICAgIHRpbWVab25lID0gdGhpcy5sb2NhbGUudGltZVpvbmVcclxuICAgICk6IHN0cmluZyB7XHJcbiAgICAgICAgdmFsdWUgPSB0b0RhdGUodmFsdWUpO1xyXG5cclxuICAgICAgICBsZXQgZGF0ZVRpbWVGb3JtYXRPcHRpb25zOiBJbnRsLkRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHt9O1xyXG4gICAgICAgIGlmIChvcHRpb25zKSB7XHJcbiAgICAgICAgICAgIGlmIChvcHRpb25zKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB7IGRhdGVTdHlsZSwgdGltZVN0eWxlLCAuLi5yZXN0IH0gPSBvcHRpb25zO1xyXG4gICAgICAgICAgICAgICAgaWYgKGRhdGVTdHlsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGRhdGVUaW1lRm9ybWF0T3B0aW9ucyA9IHsgLi4uZGF0ZVRpbWVGb3JtYXRPcHRpb25zLCAuLi5QQVJTRV9EQVRFX1NUWUxFW2RhdGVTdHlsZV0gfTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmICh0aW1lU3R5bGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBkYXRlVGltZUZvcm1hdE9wdGlvbnMgPSB7IC4uLmRhdGVUaW1lRm9ybWF0T3B0aW9ucywgLi4uUEFSU0VfVElNRV9TVFlMRVt0aW1lU3R5bGVdIH07XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBkYXRlVGltZUZvcm1hdE9wdGlvbnMgPSB7IC4uLmRhdGVUaW1lRm9ybWF0T3B0aW9ucywgLi4ucmVzdCB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0aW1lWm9uZSkge1xyXG4gICAgICAgICAgICBkYXRlVGltZUZvcm1hdE9wdGlvbnMudGltZVpvbmUgPSB0aW1lWm9uZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChsYW5ndWFnZSwgZGF0ZVRpbWVGb3JtYXRPcHRpb25zKS5mb3JtYXQodmFsdWUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRm9ybWF0cyBhIG51bWJlci5cclxuICAgICAqIEBwYXJhbSB2YWx1ZSBBIG51bWJlciBvciBhIHN0cmluZ1xyXG4gICAgICogQHBhcmFtIG9wdGlvbnMgQSBMMTBuIG9yIEludGwgTnVtYmVyRm9ybWF0T3B0aW9ucyBvYmplY3RcclxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSBUaGUgY3VycmVudCBsYW5ndWFnZVxyXG4gICAgICogQHBhcmFtIGN1cnJlbmN5IFRoZSBjdXJyZW50IGN1cnJlbmN5XHJcbiAgICAgKiBAcGFyYW0gY29udmVydCBBbiBvcHRpb25hbCBmdW5jdGlvbiB0byBjb252ZXJ0IHRoZSB2YWx1ZSwgd2l0aCB2YWx1ZSBhbmQgbG9jYWxlIGluIHRoZSBzaWduYXR1cmUuIFxyXG4gICAgICogRm9yIGV4YW1wbGU6XHJcbiAgICAgKiBgYGBcclxuICAgICAqIGNvbnN0IGNvbnZlcnQgPSAodmFsdWU6IG51bWJlciwgbG9jYWxlOiBMMTBuTG9jYWxlKSA9PiB7IHJldHVybiAuLi4gfTtcclxuICAgICAqIGBgYFxyXG4gICAgICogQHBhcmFtIGNvbnZlcnRQYXJhbXMgT3B0aW9uYWwgcGFyYW1ldGVycyBmb3IgdGhlIGNvbnZlcnQgZnVuY3Rpb25cclxuICAgICAqL1xyXG4gICAgcHVibGljIGZvcm1hdE51bWJlcihcclxuICAgICAgICB2YWx1ZTogYW55LFxyXG4gICAgICAgIG9wdGlvbnM/OiBMMTBuTnVtYmVyRm9ybWF0T3B0aW9ucyxcclxuICAgICAgICBsYW5ndWFnZSA9IHRoaXMubG9jYWxlLm51bWJlckxhbmd1YWdlIHx8IHRoaXMubG9jYWxlLmxhbmd1YWdlLFxyXG4gICAgICAgIGN1cnJlbmN5ID0gdGhpcy5sb2NhbGUuY3VycmVuY3ksXHJcbiAgICAgICAgY29udmVydD86ICh2YWx1ZTogbnVtYmVyLCBsb2NhbGU6IEwxMG5Mb2NhbGUsIHBhcmFtczogYW55KSA9PiBudW1iZXIsXHJcbiAgICAgICAgY29udmVydFBhcmFtcz86IGFueVxyXG4gICAgKTogc3RyaW5nIHtcclxuICAgICAgICBpZiAob3B0aW9ucyAmJiBvcHRpb25zWydzdHlsZSddID09PSAndW5pdCcgJiYgIW9wdGlvbnNbJ3VuaXQnXSkgcmV0dXJuIHZhbHVlO1xyXG5cclxuICAgICAgICB2YWx1ZSA9IHRvTnVtYmVyKHZhbHVlKTtcclxuXHJcbiAgICAgICAgLy8gT3B0aW9uYWwgY29udmVyc2lvbi5cclxuICAgICAgICBpZiAodHlwZW9mIGNvbnZlcnQgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgdmFsdWUgPSBjb252ZXJ0KHZhbHVlLCB0aGlzLmxvY2FsZSwgT2JqZWN0LnZhbHVlcyhjb252ZXJ0UGFyYW1zIHx8IHt9KSk7IC8vIERlc3RydWN0dXJlcyBwYXJhbXNcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBudW1iZXJGb3JtYXRPcHRpb25zOiBJbnRsLk51bWJlckZvcm1hdE9wdGlvbnMgPSB7fTtcclxuICAgICAgICBpZiAob3B0aW9ucykge1xyXG4gICAgICAgICAgICBjb25zdCB7IGRpZ2l0cywgLi4ucmVzdCB9ID0gb3B0aW9ucztcclxuICAgICAgICAgICAgaWYgKGRpZ2l0cykge1xyXG4gICAgICAgICAgICAgICAgbnVtYmVyRm9ybWF0T3B0aW9ucyA9IHsgLi4ubnVtYmVyRm9ybWF0T3B0aW9ucywgLi4ucGFyc2VEaWdpdHMoZGlnaXRzKSB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG51bWJlckZvcm1hdE9wdGlvbnMgPSB7IC4uLm51bWJlckZvcm1hdE9wdGlvbnMsIC4uLnJlc3QgfTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGN1cnJlbmN5KSBudW1iZXJGb3JtYXRPcHRpb25zLmN1cnJlbmN5ID0gY3VycmVuY3k7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgSW50bC5OdW1iZXJGb3JtYXQobGFuZ3VhZ2UsIG51bWJlckZvcm1hdE9wdGlvbnMpLmZvcm1hdCh2YWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBGb3JtYXRzIGEgcmVsYXRpdmUgdGltZS5cclxuICAgICAqIEBwYXJhbSB2YWx1ZSBBIG5lZ2F0aXZlIChvciBwb3NpdGl2ZSkgbnVtYmVyXHJcbiAgICAgKiBAcGFyYW0gdW5pdCBBbiBJbnRsIFJlbGF0aXZlVGltZUZvcm1hdFVuaXQgdmFsdWVcclxuICAgICAqIEBwYXJhbSBvcHRpb25zIEFuIEludGwgUmVsYXRpdmVUaW1lRm9ybWF0T3B0aW9ucyBvYmplY3RcclxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSBUaGUgY3VycmVudCBsYW5ndWFnZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZm9ybWF0UmVsYXRpdmVUaW1lKFxyXG4gICAgICAgIHZhbHVlOiBhbnksXHJcbiAgICAgICAgdW5pdDogSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXRVbml0LFxyXG4gICAgICAgIG9wdGlvbnM/OiBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdE9wdGlvbnMsXHJcbiAgICAgICAgbGFuZ3VhZ2UgPSB0aGlzLmxvY2FsZS5kYXRlTGFuZ3VhZ2UgfHwgdGhpcy5sb2NhbGUubGFuZ3VhZ2VcclxuICAgICk6IHN0cmluZyB7XHJcbiAgICAgICAgdmFsdWUgPSB0b051bWJlcih2YWx1ZSk7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXQobGFuZ3VhZ2UsIG9wdGlvbnMpLmZvcm1hdCh2YWx1ZSwgdW5pdCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBwbHVyYWwgYnkgYSBudW1iZXIuXHJcbiAgICAgKiBUaGUgJ3ZhbHVlJyBpcyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIgdG8gdGhlIHRyYW5zbGF0aW9uIGZ1bmN0aW9uLlxyXG4gICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1iZXIgdG8gZ2V0IHRoZSBwbHVyYWxcclxuICAgICAqIEBwYXJhbSBwcmVmaXggT3B0aW9uYWwgcHJlZml4IGZvciB0aGUga2V5XHJcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBBbiBJbnRsIFBsdXJhbFJ1bGVzT3B0aW9ucyBvYmplY3RcclxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSBUaGUgY3VycmVudCBsYW5ndWFnZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcGx1cmFsKHZhbHVlOiBhbnksIHByZWZpeCA9ICcnLCBvcHRpb25zPzogSW50bC5QbHVyYWxSdWxlc09wdGlvbnMsIGxhbmd1YWdlID0gdGhpcy5sb2NhbGUubGFuZ3VhZ2UpOiBzdHJpbmcge1xyXG4gICAgICAgIHZhbHVlID0gdG9OdW1iZXIodmFsdWUpO1xyXG5cclxuICAgICAgICBjb25zdCBydWxlID0gbmV3IEludGwuUGx1cmFsUnVsZXMobGFuZ3VhZ2UsIG9wdGlvbnMpLnNlbGVjdCh2YWx1ZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IGtleSA9IHByZWZpeCA/IGAke3ByZWZpeH0ke3RoaXMuY29uZmlnLmtleVNlcGFyYXRvcn0ke3J1bGV9YCA6IHJ1bGU7XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZShrZXksIHsgdmFsdWUgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRyYW5zbGF0aW9uIG9mIGxhbmd1YWdlLCByZWdpb24sIHNjcmlwdCBvciBjdXJyZW5jeSBkaXNwbGF5IG5hbWVzXHJcbiAgICAgKiBAcGFyYW0gY29kZSBJU08gY29kZSBvZiBsYW5ndWFnZSwgcmVnaW9uLCBzY3JpcHQgb3IgY3VycmVuY3lcclxuICAgICAqIEBwYXJhbSBvcHRpb25zIEFuIEludGwgRGlzcGxheU5hbWVzT3B0aW9ucyBvYmplY3RcclxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSBUaGUgY3VycmVudCBsYW5ndWFnZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZGlzcGxheU5hbWVzKGNvZGU6IHN0cmluZywgb3B0aW9uczogSW50bC5EaXNwbGF5TmFtZXNPcHRpb25zLCBsYW5ndWFnZSA9IHRoaXMubG9jYWxlLmxhbmd1YWdlKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gbmV3IEludGwuRGlzcGxheU5hbWVzKGxhbmd1YWdlLCBvcHRpb25zKS5vZihjb2RlKSB8fCBjb2RlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXRDdXJyZW5jeVN5bWJvbChsb2NhbGUgPSB0aGlzLmxvY2FsZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XHJcbiAgICAgICAgY29uc3QgZGVjaW1hbCA9IHRoaXMuZm9ybWF0TnVtYmVyKDAsIHsgZGlnaXRzOiAnMS4wLTAnIH0sIGxvY2FsZS5udW1iZXJMYW5ndWFnZSB8fCBsb2NhbGUubGFuZ3VhZ2UpO1xyXG4gICAgICAgIGNvbnN0IGN1cnJlbmN5ID0gdGhpcy5mb3JtYXROdW1iZXIoXHJcbiAgICAgICAgICAgIDAsXHJcbiAgICAgICAgICAgIHsgZGlnaXRzOiAnMS4wLTAnLCBzdHlsZTogJ2N1cnJlbmN5JywgY3VycmVuY3lEaXNwbGF5OiAnc3ltYm9sJyB9LFxyXG4gICAgICAgICAgICBsb2NhbGUubnVtYmVyTGFuZ3VhZ2UgfHwgbG9jYWxlLmxhbmd1YWdlLFxyXG4gICAgICAgICAgICBsb2NhbGUuY3VycmVuY3lcclxuICAgICAgICApO1xyXG4gICAgICAgIGxldCBzeW1ib2wgPSBjdXJyZW5jeS5yZXBsYWNlKGRlY2ltYWwsICcnKTtcclxuICAgICAgICBzeW1ib2wgPSBzeW1ib2wudHJpbSgpO1xyXG5cclxuICAgICAgICByZXR1cm4gc3ltYm9sO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29tcGFyZXMgdHdvIGtleXMgYnkgdGhlIHZhbHVlIG9mIHRyYW5zbGF0aW9uLlxyXG4gICAgICogQHBhcmFtIGtleTEgRmlyc3Qga2V5IHRvIGNvbXBhcmVcclxuICAgICAqIEBwYXJhbSBrZXkxIFNlY29uZCBrZXkgdG8gY29tcGFyZVxyXG4gICAgICogQHBhcmFtIG9wdGlvbnMgQW4gSW50bCBDb2xsYXRvck9wdGlvbnMgb2JqZWN0XHJcbiAgICAgKiBAcGFyYW0gbGFuZ3VhZ2UgVGhlIGN1cnJlbnQgbGFuZ3VhZ2VcclxuICAgICAqIEByZXR1cm4gQSBuZWdhdGl2ZSB2YWx1ZSBpZiB0aGUgdmFsdWUgb2YgdHJhbnNsYXRpb24gb2Yga2V5MSBjb21lcyBiZWZvcmUgdGhlIHZhbHVlIG9mIHRyYW5zbGF0aW9uIG9mIGtleTI7XHJcbiAgICAgKiAgICAgICAgIGEgcG9zaXRpdmUgdmFsdWUgaWYga2V5MSBjb21lcyBhZnRlciBrZXkyO1xyXG4gICAgICogICAgICAgICAwIGlmIHRoZXkgYXJlIGNvbnNpZGVyZWQgZXF1YWwgb3IgSW50bC5Db2xsYXRvciBpcyBub3Qgc3VwcG9ydGVkXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb21wYXJlKGtleTE6IHN0cmluZywga2V5Mjogc3RyaW5nLCBvcHRpb25zPzogSW50bC5Db2xsYXRvck9wdGlvbnMsIGxhbmd1YWdlID0gdGhpcy5sb2NhbGUubGFuZ3VhZ2UpOiBudW1iZXIge1xyXG4gICAgICAgIGNvbnN0IHZhbHVlMSA9IHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKGtleTEpO1xyXG4gICAgICAgIGNvbnN0IHZhbHVlMiA9IHRoaXMudHJhbnNsYXRpb24udHJhbnNsYXRlKGtleTIpO1xyXG5cclxuICAgICAgICByZXR1cm4gbmV3IEludGwuQ29sbGF0b3IobGFuZ3VhZ2UsIG9wdGlvbnMpLmNvbXBhcmUodmFsdWUxLCB2YWx1ZTIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgcmVwcmVzZW50YXRpb24gb2YgYSBsaXN0LlxyXG4gICAgICogQHBhcmFtIGxpc3QgQW4gYXJyYXkgb2Yga2V5c1xyXG4gICAgICogQHBhcmFtIG9wdGlvbnMgQW4gSW50bCBMaXN0Rm9ybWF0T3B0aW9ucyBvYmplY3RcclxuICAgICAqIEBwYXJhbSBsYW5ndWFnZSBUaGUgY3VycmVudCBsYW5ndWFnZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbGlzdChsaXN0OiBzdHJpbmdbXSwgb3B0aW9ucz86IEludGwuTGlzdEZvcm1hdE9wdGlvbnMsIGxhbmd1YWdlID0gdGhpcy5sb2NhbGUubGFuZ3VhZ2UpOiBzdHJpbmcge1xyXG4gICAgICAgIGNvbnN0IHZhbHVlcyA9IGxpc3QubWFwKGtleSA9PiB0aGlzLnRyYW5zbGF0aW9uLnRyYW5zbGF0ZShrZXkpKTtcclxuICAgICAgICBpZiAobGFuZ3VhZ2UgPT0gbnVsbCB8fCBsYW5ndWFnZSA9PT0gJycpIHJldHVybiB2YWx1ZXMuam9pbignLCAnKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRsLkxpc3RGb3JtYXQobGFuZ3VhZ2UsIG9wdGlvbnMpLmZvcm1hdCh2YWx1ZXMpO1xyXG4gICAgfVxyXG5cclxufVxyXG4iXX0=