angular-l10n
Version:
Angular library to translate texts, dates and numbers
152 lines • 23.9 kB
JavaScript
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=