@ngx-easy-i18n-js/core
Version:
The easy internationalization (i18n) library for Angular
1,124 lines (1,107 loc) • 49.4 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, InjectionToken, Inject, LOCALE_ID, Pipe, Input, Directive, DEFAULT_CURRENCY_CODE, ContentChildren, NgModule, provideAppInitializer, inject } from '@angular/core';
import { registerLocaleData, formatDate, formatNumber, formatPercent, getCurrencySymbol, formatCurrency } from '@angular/common';
import { of, defer, BehaviorSubject, ReplaySubject, switchMap, forkJoin, firstValueFrom, filter, merge } from 'rxjs';
import { installEasyI18n, setEasyI18nMessages, tr, plural } from 'easy-i18n-js';
import * as lodash from 'lodash';
import { tap, catchError, map } from 'rxjs/operators';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
class EasyI18nLoader {
}
/**
* This loader is just a placeholder that does nothing, in case you don't need a loader at all
*/
class EmptyEasyI18nLoader extends EasyI18nLoader {
getMessages(locale) {
return of({});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EmptyEasyI18nLoader, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EmptyEasyI18nLoader }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EmptyEasyI18nLoader, decorators: [{
type: Injectable
}] });
class EasyI18nStore {
}
/**
* This store, get stored culture
*/
class EmptyEasyI18nStore extends EasyI18nStore {
get() {
return of(null);
}
save(locale) {
return of(true);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EmptyEasyI18nStore, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EmptyEasyI18nStore }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EmptyEasyI18nStore, decorators: [{
type: Injectable
}] });
/**
* Use localStorage
*/
class LocalStorageEasyI18nStore extends EasyI18nStore {
constructor(key) {
super();
this.key = key;
}
get() {
return defer(() => of(localStorage.getItem(this.key)));
}
save(locale) {
return defer(() => {
localStorage.setItem(this.key, locale);
return of(true);
});
}
}
const EASY_I18N_OPTIONS = new InjectionToken('EASY_I18N_OPTIONS');
const NG_LOCALES = new InjectionToken('NG_LOCALES');
const USE_BROWSER_LANGUAGE = new InjectionToken('USE_BROWSER_LANGUAGE');
const DEFAULT_LANGUAGE = new InjectionToken('DEFAULT_LANGUAGE');
const FALLBACK_LANGUAGE = new InjectionToken('FALLBACK_LANGUAGE');
const DISCOVER = new InjectionToken('DISCOVER');
const cultureRegex = new RegExp('^([a-z]{2,3})(?:-([A-Z]{2,3})(?:-([a-zA-Z]{4}))?)?$');
function getPossibleLocales(culture, discover) {
if (!culture) {
return [];
}
if (discover === 'exact') {
return [culture];
}
const match = culture.match(cultureRegex);
if (discover === 'minimum') {
return lodash.compact([match?.[1]]);
}
return lodash.compact(lodash.uniq([match?.[0], lodash.compact([match?.[1], match?.[2]]).join('-'), match?.[1]]));
}
class EasyI18nService {
// Get status observable of loading locale
get localeStatus$() {
return this._localeStatusSubject.asObservable();
}
// Get locale observable
get locale$() {
return this._localeSubject.asObservable();
}
// Current locale
get currentLocale() {
return this._currentLocale;
}
// Current Angular locale
get ngLocale() {
return this._ngLocale;
}
constructor(options, ngLocales, useBrowserLanguage, defaultLanguage, fallbackLanguage, discover, loader, store, destroyRef) {
this.options = options;
this.ngLocales = ngLocales;
this.useBrowserLanguage = useBrowserLanguage;
this.defaultLanguage = defaultLanguage;
this.fallbackLanguage = fallbackLanguage;
this.discover = discover;
this.loader = loader;
this.store = store;
this.destroyRef = destroyRef;
this._localeStatusSubject = new BehaviorSubject('none');
this._localeSubject = new ReplaySubject(1);
this._currentLocale = null;
this._ngLocale = null;
this.otherLoaders = [];
this.currentMsg = {};
installEasyI18n(options);
}
async initialize() {
this._localeSubject.asObservable().pipe(takeUntilDestroyed(this.destroyRef), tap(() => this._localeStatusSubject.next('loading')), switchMap(culture => {
const ngLocale = getPossibleLocales(culture, 'all').find(l => this.ngLocales?.[l]);
if (ngLocale != null) {
registerLocaleData(this.ngLocales[ngLocale]);
this._ngLocale = ngLocale;
}
else {
console.warn(`Not found locale data for currentLocale ${culture}`);
if (culture !== (this.fallbackLanguage ?? this.defaultLanguage)) {
const defaultNgLocale = getPossibleLocales(this.fallbackLanguage ?? this.defaultLanguage, 'all').find(l => this.ngLocales?.[l]);
if (defaultNgLocale != null) {
console.warn(`Use locale data with ${this.fallbackLanguage ?? this.defaultLanguage}`);
registerLocaleData(this.ngLocales[defaultNgLocale]);
this._ngLocale = defaultNgLocale;
}
else {
console.warn(`Not found locale data for defaultLanguage ${this.fallbackLanguage ?? this.defaultLanguage}`);
this._ngLocale = null;
}
}
}
const locales = lodash.uniq([...getPossibleLocales(culture, this.discover), ...getPossibleLocales(this.fallbackLanguage ?? this.defaultLanguage, this.discover)]);
return forkJoin(locales.flatMap(locale => [
this.loader.getMessages(locale).pipe(catchError(() => {
return of({});
})),
...this.otherLoaders.map(l => l.getMessages(locale).pipe(catchError(() => {
return of({});
})))
])).pipe(map(res => lodash.defaultsDeep({}, ...lodash.compact(res))), tap(msg => {
this.currentMsg = msg ?? {};
setEasyI18nMessages(this.currentMsg, culture);
this._currentLocale = lodash.head(locales) ?? culture;
}));
}), tap(() => this._localeStatusSubject.next('ready'))).subscribe();
this.store.get().pipe(takeUntilDestroyed(this.destroyRef), tap(stored => {
const culture = stored ?? (this.useBrowserLanguage ? this.getBrowserCulture() : null) ?? this.defaultLanguage;
if (!culture || !cultureRegex.test(culture)) {
console.error(`Culture ${culture} is wrong format`);
return;
}
this._localeSubject.next(culture);
})).subscribe();
return firstValueFrom(this._localeStatusSubject.asObservable().pipe(filter(s => s === 'ready')));
}
/**
* Get plain message by key
*
* @param key key
*/
getPlainMessage(key) {
return lodash.get(this.currentMsg, key);
}
/**
* Change current culture
*
* @param culture new culture
* @param options
*/
registerCulture(culture, options) {
if (!culture || !cultureRegex.test(culture)) {
console.error(`Culture ${culture} is wrong format`);
return;
}
this.store.save(culture).pipe(tap(() => {
if (options?.reload) {
location.reload();
}
else {
this._localeSubject.next(culture);
}
})).subscribe();
}
/**
* Get browser culture
*/
getBrowserCulture() {
if (typeof window === 'undefined' || typeof window.navigator === 'undefined') {
return null;
}
let browserCultureLang = window.navigator.languages ? window.navigator.languages[0] : null;
return browserCultureLang ?? window.navigator.language ??
window.navigator.browserLanguage ?? window.navigator.userLanguage;
}
async appendLoader(loader) {
this.otherLoaders.push(loader);
return firstValueFrom(this._localeStatusSubject.asObservable().pipe(filter(s => s === 'ready'), switchMap(() => {
const locales = lodash.uniq([...getPossibleLocales(this._currentLocale, this.discover), ...getPossibleLocales(this.fallbackLanguage ?? this.defaultLanguage, this.discover)]);
return forkJoin(locales.map(locale => loader.getMessages(locale).pipe(catchError(() => {
return of({});
})))).pipe(map(res => lodash.defaultsDeep(this.currentMsg, ...lodash.compact(res))), tap(msg => {
setEasyI18nMessages(msg, this._currentLocale);
}), map(() => true));
})), {
defaultValue: false
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EasyI18nService, deps: [{ token: EASY_I18N_OPTIONS }, { token: NG_LOCALES }, { token: USE_BROWSER_LANGUAGE }, { token: DEFAULT_LANGUAGE }, { token: FALLBACK_LANGUAGE }, { token: DISCOVER }, { token: EasyI18nLoader }, { token: EasyI18nStore }, { token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EasyI18nService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EasyI18nService, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Inject,
args: [EASY_I18N_OPTIONS]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [NG_LOCALES]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [USE_BROWSER_LANGUAGE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [DEFAULT_LANGUAGE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [FALLBACK_LANGUAGE]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [DISCOVER]
}] }, { type: EasyI18nLoader }, { type: EasyI18nStore }, { type: i0.DestroyRef }] });
class LocaleDatePipe {
constructor(easyI18nService, localeId) {
this.easyI18nService = easyI18nService;
this.localeId = localeId;
}
transform(value, format, timezone) {
return formatDate(value, format, this.easyI18nService.ngLocale ?? this.localeId, timezone);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocaleDatePipe, deps: [{ token: EasyI18nService }, { token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: LocaleDatePipe, isStandalone: true, name: "localeDate" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocaleDatePipe, decorators: [{
type: Pipe,
args: [{
name: 'localeDate',
standalone: true
}]
}], ctorParameters: () => [{ type: EasyI18nService }, { type: undefined, decorators: [{
type: Inject,
args: [LOCALE_ID]
}] }] });
class LocaleNumberPipe {
constructor(easyI18nService, localeId) {
this.easyI18nService = easyI18nService;
this.localeId = localeId;
}
transform(value, digitsInfo) {
return formatNumber(value, this.easyI18nService.ngLocale ?? this.localeId, digitsInfo);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocaleNumberPipe, deps: [{ token: EasyI18nService }, { token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: LocaleNumberPipe, isStandalone: true, name: "localeNumber" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocaleNumberPipe, decorators: [{
type: Pipe,
args: [{
name: 'localeNumber',
standalone: true
}]
}], ctorParameters: () => [{ type: EasyI18nService }, { type: undefined, decorators: [{
type: Inject,
args: [LOCALE_ID]
}] }] });
class TrDirective {
set trKey(key) {
if (key !== this.currentKey) {
this.currentKey = key;
this.render(true);
}
}
set trNamespace(namespace) {
if (namespace !== this.currentParams?.namespace) {
this.currentParams = {
...(this.currentParams ?? {}),
namespace
};
this.render(true);
}
}
set trGender(gender) {
if (gender !== this.currentParams?.gender) {
this.currentParams = {
...(this.currentParams ?? {}),
gender
};
this.render(true);
}
}
set trArgs(args) {
if (!lodash.isEqual(args, this.currentParams?.args)) {
this.currentParams = {
...(this.currentParams ?? {}),
args
};
this.render(true);
}
}
set trNamedArgs(namedArgs) {
if (!lodash.isEqual(namedArgs, this.currentParams?.namedArgs)) {
this.currentParams = {
...(this.currentParams ?? {}),
namedArgs
};
this.render(true);
}
}
constructor(el) {
this.el = el;
this.changes = new MutationObserver(() => {
this.render();
});
this.changes.observe(el.nativeElement, {
childList: true,
characterData: true,
subtree: true
});
}
ngOnDestroy() {
this.changes.disconnect();
}
render(paramsOnly = false) {
const nodes = this.el.nativeElement.childNodes;
nodes.forEach((node) => {
if (node.nodeType === 3) { // Seulement les node de type 3, text
if (node.lookupKey != null) {
this.updateValue(node.lookupKey, node);
}
else if (this.currentKey != null) {
this.updateValue(this.currentKey, this.el.nativeElement);
}
else {
let key = null;
const content = this.getContent(node);
node.lookupKey = content.trim();
// Si le contenu actuel est différent de la valeur traduite, la clef a changé
if (content !== node.currentValue) {
key = node.lookupKey;
// On stocke la valeur originale qui doit ête la clef
node.originalContent = content ?? node.originalContent;
}
else if (node.originalContent && paramsOnly) { // Le contenu actuel est la version traduite, si on a l'original
// On prend la clef originale et on va vérifier si un paramètre a changé
key = node.originalContent.trim();
}
this.updateValue(key, node);
}
}
});
}
updateValue(key, node) {
if (!key) {
return;
}
// Si rien n'a changé on arrête
if (node.lastKey === key && this.lastParams === this.currentParams) {
return;
}
node.lastKey = key;
this.lastParams = this.currentParams;
if (!node.originalContent) {
node.originalContent = this.getContent(node);
}
const res = tr(key, this.currentParams);
if (this.currentKey && res === key) {
return;
}
node.currentValue = res ?? node.originalContent ?? key;
this.setContent(node, this.currentKey ? node.currentValue : node.originalContent.replace(key, node.currentValue));
}
getContent(node) {
return node.textContent != null ? node.textContent : node.data;
}
setContent(node, content) {
if (node.textContent != null) {
node.textContent = content;
}
else {
node.data = content;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: TrDirective, isStandalone: true, selector: "[tr]", inputs: { trKey: "trKey", trNamespace: "trNamespace", trGender: "trGender", trArgs: "trArgs", trNamedArgs: "trNamedArgs" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrDirective, decorators: [{
type: Directive,
args: [{
selector: '[tr]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { trKey: [{
type: Input
}], trNamespace: [{
type: Input
}], trGender: [{
type: Input
}], trArgs: [{
type: Input
}], trNamedArgs: [{
type: Input
}] } });
class TrPipe {
transform(text, options) {
if (!text) {
return text;
}
return tr(text, options);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: TrPipe, isStandalone: true, name: "tr" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrPipe, decorators: [{
type: Pipe,
args: [{
name: 'tr',
standalone: true
}]
}] });
class PluralPipe {
transform(text, value, options) {
if (!text) {
return text;
}
return plural(text, value, options);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: PluralPipe, isStandalone: true, name: "plural" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralPipe, decorators: [{
type: Pipe,
args: [{
name: 'plural',
standalone: true
}]
}] });
class PluralDirective {
set plural(value) {
if (value !== this.currentValue) {
this.currentValue = value;
this.render(true);
}
}
set pluralKey(key) {
if (key !== this.currentKey) {
this.currentKey = key;
this.render(true);
}
}
set pluralNamespace(namespace) {
if (namespace !== this.currentParams?.namespace) {
this.currentParams = {
...(this.currentParams ?? {}),
namespace
};
this.render(true);
}
}
set pluralGender(gender) {
if (gender !== this.currentParams?.gender) {
this.currentParams = {
...(this.currentParams ?? {}),
gender
};
this.render(true);
}
}
set pluralArgs(args) {
if (!lodash.isEqual(args, this.currentParams?.args)) {
this.currentParams = {
...(this.currentParams ?? {}),
args
};
this.render(true);
}
}
set pluralNamedArgs(namedArgs) {
if (!lodash.isEqual(namedArgs, this.currentParams?.namedArgs)) {
this.currentParams = {
...(this.currentParams ?? {}),
namedArgs
};
this.render(true);
}
}
set pluralName(name) {
if (name !== this.currentParams?.name) {
this.currentParams = {
...(this.currentParams ?? {}),
name
};
this.render(true);
}
}
set pluralNumberFormatterFn(numberFormatterFn) {
if (numberFormatterFn !== this.currentParams?.numberFormatterFn) {
this.currentParams = {
...(this.currentParams ?? {}),
numberFormatterFn
};
this.render(true);
}
}
constructor(el) {
this.el = el;
this.changes = new MutationObserver(() => {
this.render();
});
this.changes.observe(el.nativeElement, {
childList: true,
characterData: true,
subtree: true
});
}
ngOnDestroy() {
this.changes.disconnect();
}
render(paramsOnly = false) {
const nodes = this.el.nativeElement.childNodes;
if (this.currentKey) {
this.updateValue(this.currentKey, this.el.nativeElement);
}
else {
nodes.forEach((node) => {
if (node.nodeType === 3) { // Seulement les node de type 3, text
let key = null;
const content = this.getContent(node);
// Si le contenu actuel est différent de la valeur traduite, la clef a changé
if (content !== node.currentValue) {
key = content.trim();
// On stocke la valeur originale qui doit ête la clef
node.originalContent = content ?? node.originalContent;
}
else if (node.originalContent && paramsOnly) { // Le contenu actuel est la version traduite, si on a l'original
// On prend la clef originale et on va vérifier si un paramètre a changé
key = node.originalContent.trim();
}
this.updateValue(key, node);
}
});
}
}
updateValue(key, node) {
if (!key) {
return;
}
// Si rien n'a changé on arrête
if (node.lastKey === key && this.currentValue === this.lastValue && this.lastParams === this.currentParams) {
return;
}
node.lastKey = key;
this.lastValue = this.currentValue;
this.lastParams = this.currentParams;
if (!node.originalContent) {
node.originalContent = this.getContent(node);
}
const res = this.currentValue != null ? plural(key, this.currentValue, this.currentParams) : '';
// Même clef, donc non traduit
if (this.currentKey && res === key) {
return;
}
node.currentValue = res ?? node.originalContent ?? key;
this.setContent(node, this.currentKey ? node.currentValue : node.originalContent.replace(key, node.currentValue));
}
getContent(node) {
return node.textContent != null ? node.textContent : node.data;
}
setContent(node, content) {
if (node.textContent != null) {
node.textContent = content;
}
else {
node.data = content;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: PluralDirective, isStandalone: true, selector: "[plural]", inputs: { plural: "plural", pluralKey: "pluralKey", pluralNamespace: "pluralNamespace", pluralGender: "pluralGender", pluralArgs: "pluralArgs", pluralNamedArgs: "pluralNamedArgs", pluralName: "pluralName", pluralNumberFormatterFn: "pluralNumberFormatterFn" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralDirective, decorators: [{
type: Directive,
args: [{
selector: '[plural]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { plural: [{
type: Input,
args: ['plural']
}], pluralKey: [{
type: Input
}], pluralNamespace: [{
type: Input
}], pluralGender: [{
type: Input
}], pluralArgs: [{
type: Input
}], pluralNamedArgs: [{
type: Input
}], pluralName: [{
type: Input,
args: ['pluralName']
}], pluralNumberFormatterFn: [{
type: Input,
args: ['pluralNumberFormatterFn']
}] } });
class LocalePercentPipe {
constructor(easyI18nService, localeId) {
this.easyI18nService = easyI18nService;
this.localeId = localeId;
}
transform(value, digitsInfo) {
return formatPercent(value, this.easyI18nService.ngLocale ?? this.localeId, digitsInfo);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocalePercentPipe, deps: [{ token: EasyI18nService }, { token: LOCALE_ID }], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: LocalePercentPipe, isStandalone: true, name: "localePercent" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocalePercentPipe, decorators: [{
type: Pipe,
args: [{
name: 'localePercent',
standalone: true
}]
}], ctorParameters: () => [{ type: EasyI18nService }, { type: undefined, decorators: [{
type: Inject,
args: [LOCALE_ID]
}] }] });
class LocaleCurrencyPipe {
constructor(easyI18nService, localeId, defaultCurrencyCode = 'USD') {
this.easyI18nService = easyI18nService;
this.localeId = localeId;
this.defaultCurrencyCode = defaultCurrencyCode;
}
transform(value, currencyCode, display = 'symbol', digitsInfo) {
const locale = this.easyI18nService.ngLocale ?? this.localeId;
let currency = currencyCode ?? this.defaultCurrencyCode;
if (display !== 'code') {
if (display === 'symbol' || display === 'symbol-narrow') {
currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale);
}
else {
currency = display;
}
}
return formatCurrency(value, locale, currency, currencyCode, digitsInfo);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocaleCurrencyPipe, deps: [{ token: EasyI18nService }, { token: LOCALE_ID }, { token: DEFAULT_CURRENCY_CODE }], target: i0.ɵɵFactoryTarget.Pipe }); }
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: LocaleCurrencyPipe, isStandalone: true, name: "localeCurrency" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: LocaleCurrencyPipe, decorators: [{
type: Pipe,
args: [{
name: 'localeCurrency',
standalone: true
}]
}], ctorParameters: () => [{ type: EasyI18nService }, { type: undefined, decorators: [{
type: Inject,
args: [LOCALE_ID]
}] }, { type: undefined, decorators: [{
type: Inject,
args: [DEFAULT_CURRENCY_CODE]
}] }] });
class PluralElementDirective {
constructor(viewRef, templateRef) {
this.viewRef = viewRef;
this.templateRef = templateRef;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralElementDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: PluralElementDirective, isStandalone: true, selector: "[pluralElement]", inputs: { elementKey: ["pluralElement", "elementKey"] }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralElementDirective, decorators: [{
type: Directive,
args: [{
selector: '[pluralElement]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.TemplateRef }], propDecorators: { elementKey: [{
type: Input,
args: ['pluralElement']
}] } });
class PluralContentDirective {
set pluralContent(key) {
if (key !== this.currentKey) {
this.currentKey = key;
this.render();
}
}
set pluralValue(value) {
if (value !== this.currentValue) {
this.currentValue = value;
this.render();
}
}
set pluralNamespace(namespace) {
if (namespace !== this.currentParams?.namespace) {
this.currentParams = {
...(this.currentParams ?? {}),
namespace
};
this.render();
}
}
set pluralGender(gender) {
if (gender !== this.currentParams?.gender) {
this.currentParams = {
...(this.currentParams ?? {}),
gender
};
this.render();
}
}
set pluralArgs(args) {
if (!lodash.isEqual(args, this.currentParams?.args)) {
this.currentParams = {
...(this.currentParams ?? {}),
args
};
this.render();
}
}
set pluralNamedArgs(namedArgs) {
if (!lodash.isEqual(namedArgs, this.currentParams?.namedArgs)) {
this.currentParams = {
...(this.currentParams ?? {}),
namedArgs
};
this.render();
}
}
set pluralName(name) {
if (name !== this.currentParams?.name) {
this.currentParams = {
...(this.currentParams ?? {}),
name
};
this.render();
}
}
set pluralNumberFormatterFn(numberFormatterFn) {
if (numberFormatterFn !== this.currentParams?.numberFormatterFn) {
this.currentParams = {
...(this.currentParams ?? {}),
numberFormatterFn
};
this.render();
}
}
set demarc(demarc) {
if (!lodash.isEqual(demarc, this._demarc)) {
this.demarc = {
...this._demarc,
...demarc
};
this.render();
}
}
constructor(viewRef, renderer, changeDetectorRef) {
this.viewRef = viewRef;
this.renderer = renderer;
this.changeDetectorRef = changeDetectorRef;
this._demarc = { start: '{', end: '}' };
}
ngAfterContentInit() {
if (this.elements) {
this.subscription = merge(new BehaviorSubject(this.elements.toArray()), this.elements.changes).subscribe(next => this.render());
}
}
ngOnDestroy() {
this.subscription?.unsubscribe();
}
render() {
if (this.elements == null || !this.currentKey || this.currentValue == null || !this._demarc?.start || !this._demarc?.end) {
return;
}
this.viewRef.clear();
const childElements = this.viewRef.element.nativeElement.children;
for (const child of childElements) {
this.renderer.removeChild(this.viewRef.element.nativeElement, child);
}
this.viewRef.element.nativeElement.textContent = '';
const raw = plural(this.currentKey, this.currentValue, this.currentParams);
let lastTokenEnd = 0;
while (lastTokenEnd < raw.length) {
const tokenStartDemarc = raw.indexOf(this._demarc?.start, lastTokenEnd);
if (tokenStartDemarc < 0) {
break;
}
const tokenStart = tokenStartDemarc + this._demarc?.start.length;
const tokenEnd = raw.indexOf(this._demarc?.end, tokenStart);
if (tokenEnd < 0) {
throw new Error(`Encountered unterminated token in translation string '${this.currentKey}'`);
}
const tokenEndDemarc = tokenEnd + this._demarc?.end.length;
const precedingText = raw.substring(lastTokenEnd, tokenStartDemarc);
const precedingTextElement = this.renderer.createText(precedingText.replace(/ /g, '\u00A0'));
this.renderer.appendChild(this.viewRef.element.nativeElement, precedingTextElement);
const elementKey = raw.substring(tokenStart, tokenEnd);
const embeddedElementTemplate = this.elements.toArray().find(element => element.elementKey === elementKey);
if (embeddedElementTemplate) {
const embeddedElementView = embeddedElementTemplate.viewRef.createEmbeddedView(embeddedElementTemplate.templateRef);
this.renderer.appendChild(this.viewRef.element.nativeElement, embeddedElementView.rootNodes[0]);
}
else {
const missingTokenText = raw.substring(tokenStartDemarc, tokenEndDemarc);
const missingTokenElement = this.renderer.createText(missingTokenText);
this.renderer.appendChild(this.viewRef.element.nativeElement, missingTokenElement);
}
lastTokenEnd = tokenEndDemarc;
}
const trailingText = raw.substring(lastTokenEnd);
const trailingTextElement = this.renderer.createText(trailingText.replace(/ /g, '\u00A0'));
this.renderer.appendChild(this.viewRef.element.nativeElement, trailingTextElement);
this.changeDetectorRef.detectChanges();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralContentDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: PluralContentDirective, isStandalone: true, selector: "[pluralContent]", inputs: { pluralContent: "pluralContent", pluralValue: "pluralValue", pluralNamespace: "pluralNamespace", pluralGender: "pluralGender", pluralArgs: "pluralArgs", pluralNamedArgs: "pluralNamedArgs", pluralName: "pluralName", pluralNumberFormatterFn: "pluralNumberFormatterFn", demarc: "demarc" }, queries: [{ propertyName: "elements", predicate: PluralElementDirective }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: PluralContentDirective, decorators: [{
type: Directive,
args: [{
selector: '[pluralContent]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }], propDecorators: { elements: [{
type: ContentChildren,
args: [PluralElementDirective]
}], pluralContent: [{
type: Input,
args: ['pluralContent']
}], pluralValue: [{
type: Input,
args: ['pluralValue']
}], pluralNamespace: [{
type: Input
}], pluralGender: [{
type: Input
}], pluralArgs: [{
type: Input
}], pluralNamedArgs: [{
type: Input
}], pluralName: [{
type: Input,
args: ['pluralName']
}], pluralNumberFormatterFn: [{
type: Input,
args: ['pluralNumberFormatterFn']
}], demarc: [{
type: Input
}] } });
class TrElementDirective {
constructor(viewRef, templateRef) {
this.viewRef = viewRef;
this.templateRef = templateRef;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrElementDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: TrElementDirective, isStandalone: true, selector: "[trElement]", inputs: { elementKey: ["trElement", "elementKey"] }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrElementDirective, decorators: [{
type: Directive,
args: [{
selector: '[trElement]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.TemplateRef }], propDecorators: { elementKey: [{
type: Input,
args: ['trElement']
}] } });
class TrContentDirective {
set trContent(key) {
if (key !== this.currentKey) {
this.currentKey = key;
this.render();
}
}
set trNamespace(namespace) {
if (namespace !== this.currentParams?.namespace) {
this.currentParams = {
...(this.currentParams ?? {}),
namespace
};
this.render();
}
}
set trGender(gender) {
if (gender !== this.currentParams?.gender) {
this.currentParams = {
...(this.currentParams ?? {}),
gender
};
this.render();
}
}
set trArgs(args) {
if (!lodash.isEqual(args, this.currentParams?.args)) {
this.currentParams = {
...(this.currentParams ?? {}),
args
};
this.render();
}
}
set trNamedArgs(namedArgs) {
if (!lodash.isEqual(namedArgs, this.currentParams?.namedArgs)) {
this.currentParams = {
...(this.currentParams ?? {}),
namedArgs
};
this.render();
}
}
set demarc(demarc) {
if (!lodash.isEqual(demarc, this._demarc)) {
this.demarc = {
...this._demarc,
...demarc
};
this.render();
}
}
constructor(viewRef, renderer, changeDetectorRef) {
this.viewRef = viewRef;
this.renderer = renderer;
this.changeDetectorRef = changeDetectorRef;
this._demarc = { start: '{', end: '}' };
}
ngAfterContentInit() {
if (this.elements) {
this.subscription = merge(new BehaviorSubject(this.elements.toArray()), this.elements.changes).subscribe(next => this.render());
}
}
ngOnDestroy() {
this.subscription?.unsubscribe();
}
render() {
if (this.elements == null || !this.currentKey || !this._demarc?.start || !this._demarc?.end) {
return;
}
this.viewRef.clear();
const childElements = this.viewRef.element.nativeElement.children;
for (const child of childElements) {
this.renderer.removeChild(this.viewRef.element.nativeElement, child);
}
this.viewRef.element.nativeElement.textContent = '';
const raw = tr(this.currentKey, this.currentParams);
let lastTokenEnd = 0;
while (lastTokenEnd < raw.length) {
const tokenStartDemarc = raw.indexOf(this._demarc?.start, lastTokenEnd);
if (tokenStartDemarc < 0) {
break;
}
const tokenStart = tokenStartDemarc + this._demarc?.start.length;
const tokenEnd = raw.indexOf(this._demarc?.end, tokenStart);
if (tokenEnd < 0) {
throw new Error(`Encountered unterminated token in translation string '${this.currentKey}'`);
}
const tokenEndDemarc = tokenEnd + this._demarc?.end.length;
const precedingText = raw.substring(lastTokenEnd, tokenStartDemarc);
const precedingTextElement = this.renderer.createText(precedingText.replace(/ /g, '\u00A0'));
this.renderer.appendChild(this.viewRef.element.nativeElement, precedingTextElement);
const elementKey = raw.substring(tokenStart, tokenEnd);
const embeddedElementTemplate = this.elements.toArray().find(element => element.elementKey === elementKey);
if (embeddedElementTemplate) {
const embeddedElementView = embeddedElementTemplate.viewRef.createEmbeddedView(embeddedElementTemplate.templateRef);
this.renderer.appendChild(this.viewRef.element.nativeElement, embeddedElementView.rootNodes[0]);
}
else {
const missingTokenText = raw.substring(tokenStartDemarc, tokenEndDemarc);
const missingTokenElement = this.renderer.createText(missingTokenText);
this.renderer.appendChild(this.viewRef.element.nativeElement, missingTokenElement);
}
lastTokenEnd = tokenEndDemarc;
}
const trailingText = raw.substring(lastTokenEnd);
const trailingTextElement = this.renderer.createText(trailingText.replace(/ /g, '\u00A0'));
this.renderer.appendChild(this.viewRef.element.nativeElement, trailingTextElement);
this.changeDetectorRef.detectChanges();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrContentDirective, deps: [{ token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: TrContentDirective, isStandalone: true, selector: "[trContent]", inputs: { trContent: "trContent", trNamespace: "trNamespace", trGender: "trGender", trArgs: "trArgs", trNamedArgs: "trNamedArgs", demarc: "demarc" }, queries: [{ propertyName: "elements", predicate: TrElementDirective }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: TrContentDirective, decorators: [{
type: Directive,
args: [{
selector: '[trContent]',
standalone: true
}]
}], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }], propDecorators: { elements: [{
type: ContentChildren,
args: [TrElementDirective]
}], trContent: [{
type: Input,
args: ['trContent']
}], trNamespace: [{
type: Input
}], trGender: [{
type: Input
}], trArgs: [{
type: Input
}], trNamedArgs: [{
type: Input
}], demarc: [{
type: Input
}] } });
class EasyI18nModule {
/**
* Use this method in your root module to provide the EasyI18nService
*/
static forRoot(config) {
return {
ngModule: EasyI18nModule,
providers: provideEasyI18n(config)
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EasyI18nModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: EasyI18nModule, imports: [LocaleDatePipe,
LocaleNumberPipe,
TrDirective,
TrPipe,
PluralPipe,
PluralDirective,
LocalePercentPipe,
LocaleCurrencyPipe,
PluralElementDirective,
PluralContentDirective,
TrElementDirective,
TrContentDirective], exports: [LocaleDatePipe,
LocaleNumberPipe,
TrDirective,
TrPipe,
PluralPipe,
PluralDirective,
LocalePercentPipe,
LocaleCurrencyPipe,
PluralElementDirective,
PluralContentDirective,
TrElementDirective,
TrContentDirective] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EasyI18nModule }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: EasyI18nModule, decorators: [{
type: NgModule,
args: [{
imports: [
LocaleDatePipe,
LocaleNumberPipe,
TrDirective,
TrPipe,
PluralPipe,
PluralDirective,
LocalePercentPipe,
LocaleCurrencyPipe,
PluralElementDirective,
PluralContentDirective,
TrElementDirective,
TrContentDirective
],
exports: [
LocaleDatePipe,
LocaleNumberPipe,
TrDirective,
TrPipe,
PluralPipe,
PluralDirective,
LocalePercentPipe,
LocaleCurrencyPipe,
PluralElementDirective,
PluralContentDirective,
TrElementDirective,
TrContentDirective
]
}]
}] });
function provideEasyI18n(config) {
return [
config.loader || { provide: EasyI18nLoader, useClass: EmptyEasyI18nLoader },
config.store || { provide: EasyI18nStore, useClass: EmptyEasyI18nStore },
{ provide: EASY_I18N_OPTIONS, useValue: config.options },
{ provide: NG_LOCALES, useValue: config.ngLocales },
{ provide: USE_BROWSER_LANGUAGE, useValue: config.useBrowserLanguage ?? true },
{ provide: DEFAULT_LANGUAGE, useValue: config.defaultLanguage ?? 'en-US' },
{ provide: FALLBACK_LANGUAGE, useValue: config.fallbackLanguage },
{ provide: DISCOVER, useValue: config.discover ?? 'all' },
EasyI18nService,
provideAppInitializer(() => {
const initializerFn = ((easyI18nService) => {
return async () => easyI18nService.initialize();
})(inject(EasyI18nService));
return initializerFn();
})
];
}
/**
* Generated bundle index. Do not edit.
*/
export { DEFAULT_LANGUAGE, DISCOVER, EASY_I18N_OPTIONS, EasyI18nLoader, EasyI18nModule, EasyI18nService, EasyI18nStore, EmptyEasyI18nLoader, EmptyEasyI18nStore, FALLBACK_LANGUAGE, LocalStorageEasyI18nStore, LocaleCurrencyPipe, LocaleDatePipe, LocaleNumberPipe, LocalePercentPipe, NG_LOCALES, PluralContentDirective, PluralDirective, PluralElementDirective, PluralPipe, TrContentDirective, TrDirective, TrElementDirective, TrPipe, USE_BROWSER_LANGUAGE, provideEasyI18n };
//# sourceMappingURL=ngx-easy-i18n-js-core.mjs.map