UNPKG

@haiilo/ngx-intl

Version:

Standalone Angular pipes using the ECMAScript Internationalization API, which provides language sensitive string comparison, number formatting, and date and time formatting.

432 lines (423 loc) 19.5 kB
import * as i0 from '@angular/core'; import { InjectionToken, LOCALE_ID, Pipe, Inject, Optional } from '@angular/core'; const INTL_DATE_OPTIONS = new InjectionToken('IntlDateOptions'); const INTL_DATE_TIMEZONE = new InjectionToken('IntlDateTimezone'); const INTL_DATE_PRESET_SHORT = { dateStyle: 'short', timeStyle: 'short' }; const INTL_DATE_PRESET_MEDIUM = { dateStyle: 'medium', timeStyle: 'medium' }; const INTL_DATE_PRESET_LONG = { dateStyle: 'long', timeStyle: 'long' }; const INTL_DATE_PRESET_FULL = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long', hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'long' }; const INTL_DATE_PRESET_SHORT_DATE = { dateStyle: 'short' }; const INTL_DATE_PRESET_MEDIUM_DATE = { dateStyle: 'medium' }; const INTL_DATE_PRESET_LONG_DATE = { dateStyle: 'long' }; const INTL_DATE_PRESET_FULL_DATE = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' }; const INTL_DATE_PRESET_SHORT_TIME = { timeStyle: 'short' }; const INTL_DATE_PRESET_MEDIUM_TIME = { timeStyle: 'medium' }; const INTL_DATE_PRESET_LONG_TIME = { timeStyle: 'long' }; const INTL_DATE_PRESET_FULL_TIME = { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'long' }; /** * A pipe that formats a date using the Intl.DateTimeFormat API. */ class IntlDatePipe { constructor(locale, options, timezone) { this.locale = locale; this.options = options; this.timezone = timezone; } transform(value, options, ...locales) { if (value === null) { return null; } const _locales = this.getLocales(locales); const _options = this.getOptions(options); const formatValue = typeof value === 'string' ? new Date(value) : value; return new Intl.DateTimeFormat(_locales, _options).format(formatValue); } getLocales(locales) { return [...locales, this.locale]; } getOptions(options) { const presetStr = typeof options === 'string'; const presetKey = !presetStr ? options?.preset || this.options?.defaultPreset || IntlDatePipe.DEFAULT_OPTIONS.defaultPreset : options; const preset = presetKey ? (this.options?.presets?.[presetKey] || IntlDatePipe.DEFAULT_OPTIONS.presets?.[presetKey]) : undefined; const timezone = this.timezone ? { timeZone: this.timezone } : {}; return { ...timezone, ...preset, ...(!presetStr ? options : undefined) }; } } IntlDatePipe.DEFAULT_OPTIONS = { presets: { short: INTL_DATE_PRESET_SHORT, medium: INTL_DATE_PRESET_MEDIUM, long: INTL_DATE_PRESET_LONG, full: INTL_DATE_PRESET_FULL, shortDate: INTL_DATE_PRESET_SHORT_DATE, mediumDate: INTL_DATE_PRESET_MEDIUM_DATE, longDate: INTL_DATE_PRESET_LONG_DATE, fullDate: INTL_DATE_PRESET_FULL_DATE, shortTime: INTL_DATE_PRESET_SHORT_TIME, mediumTime: INTL_DATE_PRESET_MEDIUM_TIME, longTime: INTL_DATE_PRESET_LONG_TIME, fullTime: INTL_DATE_PRESET_FULL_TIME } }; IntlDatePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlDatePipe, deps: [{ token: LOCALE_ID }, { token: INTL_DATE_OPTIONS, optional: true }, { token: INTL_DATE_TIMEZONE, optional: true }], target: i0.ɵɵFactoryTarget.Pipe }); IntlDatePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: IntlDatePipe, isStandalone: true, name: "intlDate" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlDatePipe, decorators: [{ type: Pipe, args: [{ name: 'intlDate', standalone: true }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID] }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_DATE_OPTIONS] }, { type: Optional }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_DATE_TIMEZONE] }, { type: Optional }] }]; } }); const INTL_NUMBER_OPTIONS = new InjectionToken('IntlNumberOptions'); const INTL_NUMBER_PRESET_SHORT = { useGrouping: false, maximumFractionDigits: 2 }; const INTL_NUMBER_PRESET_LONG = { maximumFractionDigits: 8 }; const INTL_NUMBER_PRESET_CURRENCY = { style: 'currency', currency: 'USD' }; const INTL_NUMBER_PRESET_PERCENT = { style: 'percent' }; /** * A pipe that formats a number using the Intl.NumberFormat API. */ class IntlNumberPipe { constructor(locale, options) { this.locale = locale; this.options = options; } transform(value, options, ...locales) { if (value === null) { return null; } const _locales = this.getLocales(locales); const _options = this.getOptions(options); return new Intl.NumberFormat(_locales, _options).format(value); } getLocales(locales) { return [...locales, this.locale]; } getOptions(options) { const presetStr = typeof options === 'string'; const presetKey = !presetStr ? options?.preset || this.options?.defaultPreset || IntlNumberPipe.DEFAULT_OPTIONS.defaultPreset : options; const preset = presetKey ? (this.options?.presets?.[presetKey] || IntlNumberPipe.DEFAULT_OPTIONS.presets?.[presetKey]) : undefined; return { ...preset, ...(!presetStr ? options : undefined) }; } } IntlNumberPipe.DEFAULT_OPTIONS = { presets: { short: INTL_NUMBER_PRESET_SHORT, long: INTL_NUMBER_PRESET_LONG, currency: INTL_NUMBER_PRESET_CURRENCY, percent: INTL_NUMBER_PRESET_PERCENT } }; IntlNumberPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlNumberPipe, deps: [{ token: LOCALE_ID }, { token: INTL_NUMBER_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Pipe }); IntlNumberPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: IntlNumberPipe, isStandalone: true, name: "intlNumber" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlNumberPipe, decorators: [{ type: Pipe, args: [{ name: 'intlNumber', standalone: true }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID] }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_NUMBER_OPTIONS] }, { type: Optional }] }]; } }); const INTL_PLURAL_OPTIONS = new InjectionToken('IntlPluralOptions'); const INTL_PLURAL_PRESET_CARDINAL = { type: 'cardinal' }; const INTL_PLURAL_PRESET_ORDINAL = { type: 'ordinal' }; /** * A pipe that pluralizes a string using the Intl.PluralRules API. */ class IntlPluralPipe { constructor(locale, options) { this.locale = locale; this.options = options; } transform(value, options, ...locales) { if (value === null) { return null; } const _locales = this.getLocales(locales); const _options = this.getOptions(options); return new Intl.PluralRules(_locales, _options).select(value); } getLocales(locales) { return [...locales, this.locale]; } getOptions(options) { const presetStr = typeof options === 'string'; const presetKey = !presetStr ? options?.preset || this.options?.defaultPreset || IntlPluralPipe.DEFAULT_OPTIONS.defaultPreset : options; const preset = presetKey ? (this.options?.presets?.[presetKey] || IntlPluralPipe.DEFAULT_OPTIONS.presets?.[presetKey]) : undefined; return { ...preset, ...(!presetStr ? options : undefined) }; } } IntlPluralPipe.DEFAULT_OPTIONS = { presets: { cardinal: INTL_PLURAL_PRESET_CARDINAL, ordinal: INTL_PLURAL_PRESET_ORDINAL } }; IntlPluralPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlPluralPipe, deps: [{ token: LOCALE_ID }, { token: INTL_PLURAL_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Pipe }); IntlPluralPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: IntlPluralPipe, isStandalone: true, name: "IntlPlural" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlPluralPipe, decorators: [{ type: Pipe, args: [{ name: 'IntlPlural', standalone: true }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID] }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_PLURAL_OPTIONS] }, { type: Optional }] }]; } }); const INTL_SORT_OPTIONS = new InjectionToken('IntlSortOptions'); const INTL_SORT_PRESET_LOWER_FIRST = { caseFirst: 'lower' }; const INTL_SORT_PRESET_UPPER_FIRST = { caseFirst: 'upper' }; /** * A pipe that sorts an array of strings using the Intl.Collator API. */ class IntlSortPipe { constructor(locale, options) { this.locale = locale; this.options = options; } transform(value, options, ...locales) { if (value === null) { return null; } const _locales = this.getLocales(locales); const _options = this.getOptions(options); return value.sort(new Intl.Collator(_locales, _options).compare); } getLocales(locales) { return [...locales, this.locale]; } getOptions(options) { const presetStr = typeof options === 'string'; const presetKey = !presetStr ? options?.preset || this.options?.defaultPreset || IntlSortPipe.DEFAULT_OPTIONS.defaultPreset : options; const preset = presetKey ? (this.options?.presets?.[presetKey] || IntlSortPipe.DEFAULT_OPTIONS.presets?.[presetKey]) : undefined; return { ...preset, ...(!presetStr ? options : undefined) }; } } IntlSortPipe.DEFAULT_OPTIONS = { presets: { lowerFirst: INTL_SORT_PRESET_LOWER_FIRST, upperFirst: INTL_SORT_PRESET_UPPER_FIRST } }; IntlSortPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlSortPipe, deps: [{ token: LOCALE_ID }, { token: INTL_SORT_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Pipe }); IntlSortPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: IntlSortPipe, isStandalone: true, name: "IntlSort" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlSortPipe, decorators: [{ type: Pipe, args: [{ name: 'IntlSort', standalone: true }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID] }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_SORT_OPTIONS] }, { type: Optional }] }]; } }); const UNITS = { year: 1 * 60 * 60 * 24 * 365, years: 1 * 60 * 60 * 24 * 365, quarter: 1 * 60 * 60 * 24 * 365 / 4, quarters: 1 * 60 * 60 * 24 * 365 / 4, month: 1 * 60 * 60 * 24 * 365 / 12, months: 1 * 60 * 60 * 24 * 365 / 12, week: 1 * 60 * 60 * 24 * 7, weeks: 1 * 60 * 60 * 24 * 7, day: 1 * 60 * 60 * 24, days: 1 * 60 * 60 * 24, hour: 1 * 60 * 60, hours: 1 * 60 * 60, minute: 1 * 60, minutes: 1 * 60, second: 1, seconds: 1 }; const INTL_TIMEAGO_OPTIONS = new InjectionToken('IntlTimeagoOptions'); const INTL_TIMEAGO_PRESET_SHORT = { numeric: 'auto', style: 'short', dateOptions: 'shortDate' }; const INTL_TIMEAGO_PRESET_LONG = { numeric: 'auto', style: 'long', dateOptions: 'mediumDate' }; /** * A pipe that formats a date value to a human-readable relative-timeago string * using the Intl.RelativeTimeFormat API. */ class IntlTimeagoPipe { constructor(cdRef, ngZone, locale, options, dateOptions, dateTimezone) { this.cdRef = cdRef; this.ngZone = ngZone; this.locale = locale; this.options = options; this.lastLocales = []; this.text = null; this.intlDatePipe = new IntlDatePipe(locale, dateOptions, dateTimezone); } ngOnDestroy() { this.removeTimer(); } transform(value, options, ...locales) { if (value !== this.lastValue || options !== this.lastOptions || locales.join() !== this.lastLocales.join()) { this.lastValue = value; this.lastOptions = options; this.lastLocales = locales; this.process(); this.removeTimer(); this.createTimer(); } else { this.createTimer(); } return this.text; } process() { if (this.lastValue == null) { this.text = null; this.update = undefined; return; } const _locales = this.getLocales(this.lastLocales); const _options = this.getOptions(this.lastOptions); const now = new Date(_options.reference ?? new Date()); const then = new Date(this.lastValue); const seconds = Math.abs(Math.round((then.getTime() - now.getTime()) / 1000)); const minRelative = _options.minRelative ?? IntlTimeagoPipe.DEFAULT_OPTIONS.minRelative ?? -1; const maxRelative = _options.maxRelative ?? IntlTimeagoPipe.DEFAULT_OPTIONS.maxRelative ?? Number.MAX_SAFE_INTEGER; if (seconds < minRelative) { this.text = _options.now ?? IntlTimeagoPipe.DEFAULT_OPTIONS.now ?? ''; this.update = minRelative - seconds; } else if (seconds >= maxRelative) { this.text = this.intlDatePipe.transform(then, _options.dateOptions, ..._locales); this.update = undefined; } else { const allowed = _options.units ?? IntlTimeagoPipe.DEFAULT_OPTIONS.units; const unit = this.getUnit(seconds, allowed); const diff = this.getDiff(now, then, unit); this.text = new Intl.RelativeTimeFormat(_locales, _options).format(diff, unit); this.update = UNITS[unit] - (seconds % UNITS[unit]); } } getUnit(seconds, allowed) { const units = Object.entries(UNITS) .sort(([, a], [, b]) => a - b) .filter(([u, v]) => seconds >= v && (allowed?.includes(u) ?? true)) .reverse(); return units?.[0]?.[0] ?? allowed?.sort((a, b) => UNITS[a] - UNITS[b])?.[0] ?? 'second'; } getDiff(now, then, unit) { return Math.ceil((then.getTime() - now.getTime()) / 1000 / UNITS[unit]); } getLocales(locales) { return [...locales, this.locale]; } getOptions(options) { const presetStr = typeof options === 'string'; const presetKey = !presetStr ? options?.preset || this.options?.defaultPreset || IntlTimeagoPipe.DEFAULT_OPTIONS.defaultPreset : options; const preset = presetKey ? (this.options?.presets?.[presetKey] || IntlTimeagoPipe.DEFAULT_OPTIONS.presets?.[presetKey]) : undefined; return { ...preset, ...(!presetStr ? options : undefined) }; } createTimer() { if (this.timer || !this.update) { return; } const update = this.update; this.timer = this.ngZone.runOutsideAngular(() => window.setTimeout(() => { this.process(); this.timer = undefined; this.ngZone.run(() => this.cdRef.markForCheck()); }, update * 1000)); } removeTimer() { if (this.timer) { window.clearTimeout(this.timer); this.timer = undefined; } } } IntlTimeagoPipe.DEFAULT_OPTIONS = { presets: { short: INTL_TIMEAGO_PRESET_SHORT, long: INTL_TIMEAGO_PRESET_LONG, } }; IntlTimeagoPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlTimeagoPipe, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: LOCALE_ID }, { token: INTL_TIMEAGO_OPTIONS, optional: true }, { token: INTL_DATE_OPTIONS, optional: true }, { token: INTL_DATE_TIMEZONE, optional: true }], target: i0.ɵɵFactoryTarget.Pipe }); IntlTimeagoPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: IntlTimeagoPipe, isStandalone: true, name: "intlTimeago", pure: false }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: IntlTimeagoPipe, decorators: [{ type: Pipe, args: [{ name: 'intlTimeago', standalone: true, pure: false }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID] }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_TIMEAGO_OPTIONS] }, { type: Optional }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_DATE_OPTIONS] }, { type: Optional }] }, { type: undefined, decorators: [{ type: Inject, args: [INTL_DATE_TIMEZONE] }, { type: Optional }] }]; } }); /* * Public API Surface of ngx-intl */ /** * Generated bundle index. Do not edit. */ export { INTL_DATE_OPTIONS, INTL_DATE_PRESET_FULL, INTL_DATE_PRESET_FULL_DATE, INTL_DATE_PRESET_FULL_TIME, INTL_DATE_PRESET_LONG, INTL_DATE_PRESET_LONG_DATE, INTL_DATE_PRESET_LONG_TIME, INTL_DATE_PRESET_MEDIUM, INTL_DATE_PRESET_MEDIUM_DATE, INTL_DATE_PRESET_MEDIUM_TIME, INTL_DATE_PRESET_SHORT, INTL_DATE_PRESET_SHORT_DATE, INTL_DATE_PRESET_SHORT_TIME, INTL_DATE_TIMEZONE, INTL_NUMBER_OPTIONS, INTL_NUMBER_PRESET_CURRENCY, INTL_NUMBER_PRESET_LONG, INTL_NUMBER_PRESET_PERCENT, INTL_NUMBER_PRESET_SHORT, INTL_PLURAL_OPTIONS, INTL_PLURAL_PRESET_CARDINAL, INTL_PLURAL_PRESET_ORDINAL, INTL_SORT_OPTIONS, INTL_SORT_PRESET_LOWER_FIRST, INTL_SORT_PRESET_UPPER_FIRST, INTL_TIMEAGO_OPTIONS, INTL_TIMEAGO_PRESET_LONG, INTL_TIMEAGO_PRESET_SHORT, IntlDatePipe, IntlNumberPipe, IntlPluralPipe, IntlSortPipe, IntlTimeagoPipe }; //# sourceMappingURL=haiilo-ngx-intl.mjs.map