@jsverse/transloco-locale
Version:
The localization (l10n) library plugin for Transloco
120 lines • 17.3 kB
JavaScript
import { inject, Injectable } from '@angular/core';
import { TranslocoService } from '@jsverse/transloco';
import { BehaviorSubject } from 'rxjs';
import { distinctUntilChanged, filter, map } from 'rxjs/operators';
import { isLocaleFormat, toDate } from './helpers';
import { getDefaultOptions } from './shared';
import { TRANSLOCO_LOCALE_CONFIG, TRANSLOCO_LOCALE_CURRENCY_MAPPING, TRANSLOCO_LOCALE_DEFAULT_CURRENCY, TRANSLOCO_LOCALE_DEFAULT_LOCALE, TRANSLOCO_LOCALE_LANG_MAPPING, } from './transloco-locale.config';
import { TRANSLOCO_DATE_TRANSFORMER, TRANSLOCO_NUMBER_TRANSFORMER, } from './transloco-locale.transformers';
import * as i0 from "@angular/core";
export class TranslocoLocaleService {
translocoService = inject(TranslocoService);
langLocaleMapping = inject(TRANSLOCO_LOCALE_LANG_MAPPING);
defaultLocale = inject(TRANSLOCO_LOCALE_DEFAULT_LOCALE);
defaultCurrency = inject(TRANSLOCO_LOCALE_DEFAULT_CURRENCY);
localeCurrencyMapping = inject(TRANSLOCO_LOCALE_CURRENCY_MAPPING);
numberTransformer = inject(TRANSLOCO_NUMBER_TRANSFORMER);
dateTransformer = inject(TRANSLOCO_DATE_TRANSFORMER);
localeConfig = inject(TRANSLOCO_LOCALE_CONFIG);
_locale = this.defaultLocale || this.toLocale(this.translocoService.getActiveLang());
locale = new BehaviorSubject(this._locale);
subscription = this.translocoService.langChanges$
.pipe(map((lang) => this.toLocale(lang)), filter(Boolean))
.subscribe((locale) => this.setLocale(locale));
localeChanges$ = this.locale.asObservable().pipe(distinctUntilChanged());
getLocale() {
return this._locale;
}
setLocale(locale) {
if (!isLocaleFormat(locale)) {
console.error(`${locale} isn't a valid locale format`);
return;
}
this.locale.next(locale);
this._locale = locale;
}
/**
* Get the currency symbol for the currently set locale.
*/
getCurrencySymbol(locale = this.getLocale()) {
const currency = this.localeCurrencyMapping[locale];
const numberFormat = new Intl.NumberFormat(locale, {
style: 'currency',
currencyDisplay: 'symbol',
currency,
minimumFractionDigits: 0,
maximumFractionDigits: 0,
});
const pivot = 0;
return numberFormat
.format(pivot)
.split(pivot.toString())
.map((element) => element.trim())
.find((element) => !!element);
}
/**
* Transform a date into the locale's date format.
*
* The date expression: a `Date` object, a number
* (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime).
*
* @example
*
* localizeDate(new Date(2019, 9, 7, 12, 0, 0)) // 10/7/2019
* localizeDate(date, 'en-US', { dateStyle: 'medium', timeStyle: 'medium' }) // Sep 10, 2019, 10:46:12 PM
* localizeDate(date) 'en-US', { timeZone: 'UTC', timeStyle: 'full' } // 7:40:32 PM Coordinated Universal Time
* localizeDate(1, 'en-US', { dateStyle: 'medium' }) // Jan 1, 1970
* localizeDate('2019-02-08', 'en-US', { dateStyle: 'medium' }) // Feb 8, 2019
*/
localizeDate(date, locale = this.getLocale(), options = {}) {
const resolved = options ?? getDefaultOptions(locale, 'date', this.localeConfig);
return this.dateTransformer.transform(toDate(date), locale, resolved);
}
/**
* Transform a number into the locale's number format according to the number type.
*
* localizeNumber(1234567890, 'decimal') // 1,234,567,890
* localizeNumber(0.5, 'percent') // 50%
* localizeNumber(1000, 'currency') // $1,000.00
*/
localizeNumber(value, style, locale = this.getLocale(), options) {
let resolved = options ?? getDefaultOptions(locale, style, this.localeConfig);
if (style === 'currency') {
resolved = {
...resolved,
currency: resolved.currency || this._resolveCurrencyCode(locale),
};
}
return this.numberTransformer.transform(value, style, locale, resolved);
}
/**
* @internal
*/
_resolveCurrencyCode(locale = this.getLocale()) {
return this.localeCurrencyMapping[locale] || this.defaultCurrency;
}
ngOnDestroy() {
this.subscription?.unsubscribe();
// Caretaker note: it's important to clean up references to subscriptions since they save the `next`
// callback within its `destination` property, preventing classes from being GC'd.
this.subscription = null;
}
toLocale(val) {
if (this.langLocaleMapping[val]) {
return this.langLocaleMapping[val];
}
if (isLocaleFormat(val)) {
return val;
}
return '';
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: TranslocoLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: TranslocoLocaleService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: TranslocoLocaleService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNsb2NvLWxvY2FsZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy90cmFuc2xvY28tbG9jYWxlL3NyYy9saWIvdHJhbnNsb2NvLWxvY2FsZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQzlELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxlQUFlLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFbkUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDbkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQzdDLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsaUNBQWlDLEVBQ2pDLGlDQUFpQyxFQUNqQywrQkFBK0IsRUFDL0IsNkJBQTZCLEdBQzlCLE1BQU0sMkJBQTJCLENBQUM7QUFDbkMsT0FBTyxFQUNMLDBCQUEwQixFQUMxQiw0QkFBNEIsR0FDN0IsTUFBTSxpQ0FBaUMsQ0FBQzs7QUFZekMsTUFBTSxPQUFPLHNCQUFzQjtJQUN6QixnQkFBZ0IsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUM1QyxpQkFBaUIsR0FBRyxNQUFNLENBQUMsNkJBQTZCLENBQUMsQ0FBQztJQUMxRCxhQUFhLEdBQUcsTUFBTSxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDeEQsZUFBZSxHQUFHLE1BQU0sQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0lBQzVELHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0lBQ2xFLGlCQUFpQixHQUFHLE1BQU0sQ0FB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aW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlLCBPbkRlc3Ryb3kgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFRyYW5zbG9jb1NlcnZpY2UgfSBmcm9tICdAanN2ZXJzZS90cmFuc2xvY28nO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRpc3RpbmN0VW50aWxDaGFuZ2VkLCBmaWx0ZXIsIG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgaXNMb2NhbGVGb3JtYXQsIHRvRGF0ZSB9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgeyBnZXREZWZhdWx0T3B0aW9ucyB9IGZyb20gJy4vc2hhcmVkJztcbmltcG9ydCB7XG4gIFRSQU5TTE9DT19MT0NBTEVfQ09ORklHLFxuICBUUkFOU0xPQ09fTE9DQUxFX0NVUlJFTkNZX01BUFBJTkcsXG4gIFRSQU5TTE9DT19MT0NBTEVfREVGQVVMVF9DVVJSRU5DWSxcbiAgVFJBTlNMT0NPX0xPQ0FMRV9ERUZBVUxUX0xPQ0FMRSxcbiAgVFJBTlNMT0NPX0xPQ0FMRV9MQU5HX01BUFBJTkcsXG59IGZyb20gJy4vdHJhbnNsb2NvLWxvY2FsZS5jb25maWcnO1xuaW1wb3J0IHtcbiAgVFJBTlNMT0NPX0RBVEVfVFJBTlNGT1JNRVIsXG4gIFRSQU5TTE9DT19OVU1CRVJfVFJBTlNGT1JNRVIsXG59IGZyb20gJy4vdHJhbnNsb2NvLWxvY2FsZS50cmFuc2Zvcm1lcnMnO1xuaW1wb3J0IHtcbiAgRGF0ZUZvcm1hdE9wdGlvbnMsXG4gIExvY2FsZSxcbiAgTG9jYWxlQ29uZmlnLFxuICBOdW1iZXJTdHlsZXMsXG4gIFZhbGlkRGF0ZSxcbn0gZnJvbSAnLi90cmFuc2xvY28tbG9jYWxlLnR5cGVzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFRyYW5zbG9jb0xvY2FsZVNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIHRyYW5zbG9jb1NlcnZpY2UgPSBpbmplY3QoVHJhbnNsb2NvU2VydmljZSk7XG4gIHByaXZhdGUgbGFuZ0xvY2FsZU1hcHBpbmcgPSBpbmplY3QoVFJBTlNMT0NPX0xPQ0FMRV9MQU5HX01BUFBJTkcpO1xuICBwcml2YXRlIGRlZmF1bHRMb2NhbGUgPSBpbmplY3QoVFJBTlNMT0NPX0xPQ0FMRV9ERUZBVUxUX0xPQ0FMRSk7XG4gIHByaXZhdGUgZGVmYXVsdEN1cnJlbmN5ID0gaW5qZWN0KFRSQU5TTE9DT19MT0NBTEVfREVGQVVMVF9DVVJSRU5DWSk7XG4gIHByaXZhdGUgbG9jYWxlQ3VycmVuY3lNYXBwaW5nID0gaW5qZWN0KFRSQU5TTE9DT19MT0NBTEVfQ1VSUkVOQ1lfTUFQUElORyk7XG4gIHByaXZhdGUgbnVtYmVyVHJhbnNmb3JtZXIgPSBpbmplY3QoVFJBTlNMT0NPX05VTUJFUl9UUkFOU0ZPUk1FUik7XG4gIHByaXZhdGUgZGF0ZVRyYW5zZm9ybWVyID0gaW5qZWN0KFRSQU5TTE9DT19EQVRFX1RSQU5TRk9STUVSKTtcbiAgcHJpdmF0ZSBsb2NhbGVDb25maWc6IExvY2FsZUNvbmZpZyA9IGluamVjdChUUkFOU0xPQ09fTE9DQUxFX0NPTkZJRyk7XG5cbiAgcHJpdmF0ZSBfbG9jYWxlID1cbiAgICB0aGlzLmRlZmF1bHRMb2NhbGUgfHwgdGhpcy50b0xvY2FsZSh0aGlzLnRyYW5zbG9jb1NlcnZpY2UuZ2V0QWN0aXZlTGFuZygpKTtcbiAgcHJpdmF0ZSBsb2NhbGU6IEJlaGF2aW9yU3ViamVjdDxMb2NhbGU+ID0gbmV3IEJlaGF2aW9yU3ViamVjdCh0aGlzLl9sb2NhbGUpO1xuICBwcml2YXRlIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uIHwgbnVsbCA9IHRoaXMudHJhbnNsb2NvU2VydmljZS5sYW5nQ2hhbmdlcyRcbiAgICAucGlwZShcbiAgICAgIG1hcCgobGFuZykgPT4gdGhpcy50b0xvY2FsZShsYW5nKSksXG4gICAgICBmaWx0ZXIoQm9vbGVhbilcbiAgICApXG4gICAgLnN1YnNjcmliZSgobG9jYWxlOiBMb2NhbGUpID0+IHRoaXMuc2V0TG9jYWxlKGxvY2FsZSkpO1xuXG4gIGxvY2FsZUNoYW5nZXMkID0gdGhpcy5sb2NhbGUuYXNPYnNlcnZhYmxlKCkucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpKTtcblxuICBnZXRMb2NhbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xvY2FsZTtcbiAgfVxuXG4gIHNldExvY2FsZShsb2NhbGU6IExvY2FsZSkge1xuICAgIGlmICghaXNMb2NhbGVGb3JtYXQobG9jYWxlKSkge1xuICAgICAgY29uc29sZS5lcnJvcihgJHtsb2NhbGV9IGlzbid0IGEgdmFsaWQgbG9jYWxlIGZvcm1hdGApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMubG9jYWxlLm5leHQobG9jYWxlKTtcbiAgICB0aGlzLl9sb2NhbGUgPSBsb2NhbGU7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW5jeSBzeW1ib2wgZm9yIHRoZSBjdXJyZW50bHkgc2V0IGxvY2FsZS5cbiAgICovXG4gIGdldEN1cnJlbmN5U3ltYm9sKGxvY2FsZSA9IHRoaXMuZ2V0TG9jYWxlKCkpIHtcbiAgICBjb25zdCBjdXJyZW5jeSA9IHRoaXMubG9jYWxlQ3VycmVuY3lNYXBwaW5nW2xvY2FsZV07XG4gICAgY29uc3QgbnVtYmVyRm9ybWF0ID0gbmV3IEludGwuTnVtYmVyRm9ybWF0KGxvY2FsZSwge1xuICAgICAgc3R5bGU6ICdjdXJyZW5jeScsXG4gICAgICBjdXJyZW5jeURpc3BsYXk6ICdzeW1ib2wnLFxuICAgICAgY3VycmVuY3ksXG4gICAgICBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IDAsXG4gICAgICBtYXhpbXVtRnJhY3Rpb25EaWdpdHM6IDAsXG4gICAgfSk7XG5cbiAgICBjb25zdCBwaXZvdCA9IDA7XG5cbiAgICByZXR1cm4gbnVtYmVyRm9ybWF0XG4gICAgICAuZm9ybWF0KHBpdm90KVxuICAgICAgLnNwbGl0KHBpdm90LnRvU3RyaW5nKCkpXG4gICAgICAubWFwKChlbGVtZW50KSA9PiBlbGVtZW50LnRyaW0oKSlcbiAgICAgIC5maW5kKChlbGVtZW50KSA9PiAhIWVsZW1lbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zZm9ybSBhIGRhdGUgaW50byB0aGUgbG9jYWxlJ3MgZGF0ZSBmb3JtYXQuXG4gICAqXG4gICAqIFRoZSBkYXRlIGV4cHJlc3Npb246IGEgYERhdGVgIG9iamVjdCwgYSBudW1iZXJcbiAgICogKG1pbGxpc2Vjb25kcyBzaW5jZSBVVEMgZXBvY2gpLCBvciBhbiBJU08gc3RyaW5nIChodHRwczovL3d3dy53My5vcmcvVFIvTk9URS1kYXRldGltZSkuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqIGxvY2FsaXplRGF0ZShuZXcgRGF0ZSgyMDE5LCA5LCA3LCAxMiwgMCwgMCkpIC8vIDEwLzcvMjAxOVxuICAgKiBsb2NhbGl6ZURhdGUoZGF0ZSwgJ2VuLVVTJywgeyBkYXRlU3R5bGU6ICdtZWRpdW0nLCB0aW1lU3R5bGU6ICdtZWRpdW0nIH0pIC8vIFNlcCAxMCwgMjAxOSwgMTA6NDY6MTIgUE1cbiAgICogbG9jYWxpemVEYXRlKGRhdGUpICdlbi1VUycsIHsgdGltZVpvbmU6ICdVVEMnLCB0aW1lU3R5bGU6ICdmdWxsJyB9IC8vIDc6NDA6MzIgUE0gQ29vcmRpbmF0ZWQgVW5pdmVyc2FsIFRpbWVcbiAgICogbG9jYWxpemVEYXRlKDEsICdlbi1VUycsIHsgZGF0ZVN0eWxlOiAnbWVkaXVtJyB9KSAvLyBKYW4gMSwgMTk3MFxuICAgKiBsb2NhbGl6ZURhdGUoJzIwMTktMDItMDgnLCAnZW4tVVMnLCB7IGRhdGVTdHlsZTogJ21lZGl1bScgfSkgLy8gRmViIDgsIDIwMTlcbiAgICovXG4gIGxvY2FsaXplRGF0ZShcbiAgICBkYXRlOiBWYWxpZERhdGUsXG4gICAgbG9jYWxlOiBMb2NhbGUgPSB0aGlzLmdldExvY2FsZSgpLFxuICAgIG9wdGlvbnM6IERhdGVGb3JtYXRPcHRpb25zID0ge31cbiAgKTogc3RyaW5nIHtcbiAgICBjb25zdCByZXNvbHZlZCA9XG4gICAgICBvcHRpb25zID8/IGdldERlZmF1bHRPcHRpb25zKGxvY2FsZSwgJ2RhdGUnLCB0aGlzLmxvY2FsZUNvbmZpZyk7XG5cbiAgICByZXR1cm4gdGhpcy5kYXRlVHJhbnNmb3JtZXIudHJhbnNmb3JtKHRvRGF0ZShkYXRlKSwgbG9jYWxlLCByZXNvbHZlZCk7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtIGEgbnVtYmVyIGludG8gdGhlIGxvY2FsZSdzIG51bWJlciBmb3JtYXQgYWNjb3JkaW5nIHRvIHRoZSBudW1iZXIgdHlwZS5cbiAgICpcbiAgICogbG9jYWxpemVOdW1iZXIoMTIzNDU2Nzg5MCwgJ2RlY2ltYWwnKSAvLyAxLDIzNCw1NjcsODkwXG4gICAqIGxvY2FsaXplTnVtYmVyKDAuNSwgJ3BlcmNlbnQnKSAvLyA1MCVcbiAgICogbG9jYWxpemVOdW1iZXIoMTAwMCwgJ2N1cnJlbmN5JykgLy8gJDEsMDAwLjAwXG4gICAqL1xuICBsb2NhbGl6ZU51bWJlcihcbiAgICB2YWx1ZTogbnVtYmVyIHwgc3RyaW5nLFxuICAgIHN0eWxlOiBOdW1iZXJTdHlsZXMsXG4gICAgbG9jYWxlOiBMb2NhbGUgPSB0aGlzLmdldExvY2FsZSgpLFxuICAgIG9wdGlvbnM/OiBJbnRsLk51bWJlckZvcm1hdE9wdGlvbnNcbiAgKTogc3RyaW5nIHtcbiAgICBsZXQgcmVzb2x2ZWQgPVxuICAgICAgb3B0aW9ucyA/PyBnZXREZWZhdWx0T3B0aW9ucyhsb2NhbGUsIHN0eWxlLCB0aGlzLmxvY2FsZUNvbmZpZyk7XG5cbiAgICBpZiAoc3R5bGUgPT09ICdjdXJyZW5jeScpIHtcbiAgICAgIHJlc29sdmVkID0ge1xuICAgICAgICAuLi5yZXNvbHZlZCxcbiAgICAgICAgY3VycmVuY3k6IHJlc29sdmVkLmN1cnJlbmN5IHx8IHRoaXMuX3Jlc29sdmVDdXJyZW5jeUNvZGUobG9jYWxlKSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubnVtYmVyVHJhbnNmb3JtZXIudHJhbnNmb3JtKHZhbHVlLCBzdHlsZSwgbG9jYWxlLCByZXNvbHZlZCk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBfcmVzb2x2ZUN1cnJlbmN5Q29kZShsb2NhbGU6IExvY2FsZSA9IHRoaXMuZ2V0TG9jYWxlKCkpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVDdXJyZW5jeU1hcHBpbmdbbG9jYWxlXSB8fCB0aGlzLmRlZmF1bHRDdXJyZW5jeTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIC8vIENhcmV0YWtlciBub3RlOiBpdCdzIGltcG9ydGFudCB0byBjbGVhbiB1cCByZWZlcmVuY2VzIHRvIHN1YnNjcmlwdGlvbnMgc2luY2UgdGhleSBzYXZlIHRoZSBgbmV4dGBcbiAgICAvLyBjYWxsYmFjayB3aXRoaW4gaXRzIGBkZXN0aW5hdGlvbmAgcHJvcGVydHksIHByZXZlbnRpbmcgY2xhc3NlcyBmcm9tIGJlaW5nIEdDJ2QuXG4gICAgdGhpcy5zdWJzY3JpcHRpb24gPSBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSB0b0xvY2FsZSh2YWw6IHN0cmluZyB8IExvY2FsZSk6IExvY2FsZSB7XG4gICAgaWYgKHRoaXMubGFuZ0xvY2FsZU1hcHBpbmdbdmFsXSkge1xuICAgICAgcmV0dXJuIHRoaXMubGFuZ0xvY2FsZU1hcHBpbmdbdmFsXTtcbiAgICB9XG5cbiAgICBpZiAoaXNMb2NhbGVGb3JtYXQodmFsKSkge1xuICAgICAgcmV0dXJuIHZhbDtcbiAgICB9XG5cbiAgICByZXR1cm4gJyc7XG4gIH1cbn1cbiJdfQ==