@acorex/core 19.12.0 → 19.13.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/date-time/index.d.ts +5 -5
- package/date-time/lib/calendar.service.d.ts +8 -3
- package/date-time/lib/dateTime.config.d.ts +1 -1
- package/date-time/lib/datetime.pipe.d.ts +2 -1
- package/date-time/lib/{datetime.class.d.ts → datetime.types.d.ts} +2 -2
- package/date-time/lib/formatters/date.formatter.d.ts +12 -0
- package/date-time/lib/formatters/{datetime-formatter.d.ts → datetime.formatter.d.ts} +3 -1
- package/date-time/lib/formatters/time.formatter.d.ts +12 -0
- package/date-time/lib/{georgian.calendar.d.ts → gregorian.calendar.d.ts} +2 -2
- package/date-time/lib/{jalali.calendar.d.ts → solar-hijri.calendar.d.ts} +8 -8
- package/events/index.d.ts +0 -1
- package/fesm2022/acorex-core-components.mjs +3 -3
- package/fesm2022/acorex-core-config.mjs +3 -3
- package/fesm2022/acorex-core-date-time.mjs +282 -119
- package/fesm2022/acorex-core-date-time.mjs.map +1 -1
- package/fesm2022/acorex-core-events.mjs +4 -10
- package/fesm2022/acorex-core-events.mjs.map +1 -1
- package/fesm2022/acorex-core-file.mjs +10 -10
- package/fesm2022/acorex-core-format.mjs +78 -63
- package/fesm2022/acorex-core-format.mjs.map +1 -1
- package/fesm2022/acorex-core-image.mjs +3 -3
- package/fesm2022/acorex-core-locale-en-AU.profile-BW-_9tgT.mjs +64 -0
- package/fesm2022/acorex-core-locale-en-AU.profile-BW-_9tgT.mjs.map +1 -0
- package/fesm2022/acorex-core-locale.mjs +341 -0
- package/fesm2022/acorex-core-locale.mjs.map +1 -0
- package/fesm2022/acorex-core-network.mjs +3 -3
- package/fesm2022/acorex-core-pipes.mjs +3 -3
- package/fesm2022/acorex-core-platform.mjs +3 -3
- package/fesm2022/acorex-core-storage.mjs +9 -9
- package/fesm2022/acorex-core-translation.mjs +246 -206
- package/fesm2022/acorex-core-translation.mjs.map +1 -1
- package/fesm2022/acorex-core-utils.mjs +143 -18
- package/fesm2022/acorex-core-utils.mjs.map +1 -1
- package/fesm2022/acorex-core-validation.mjs +40 -40
- package/format/index.d.ts +2 -2
- package/format/lib/format.directive.d.ts +1 -1
- package/format/lib/format.module.d.ts +3 -3
- package/format/lib/format.service.d.ts +8 -7
- package/locale/README.md +3 -0
- package/locale/index.d.ts +8 -0
- package/locale/lib/formatters/currency.formatter.d.ts +10 -0
- package/locale/lib/locale-profile-provider.service.d.ts +24 -0
- package/locale/lib/locale.config.d.ts +5 -0
- package/locale/lib/locale.module.d.ts +7 -0
- package/locale/lib/locale.service.d.ts +20 -0
- package/locale/lib/locale.types.d.ts +61 -0
- package/locale/lib/profiles/en-AU.profile.d.ts +2 -0
- package/locale/lib/profiles/en-US.profile.d.ts +2 -0
- package/locale/lib/profiles/fa-IR.profile.d.ts +2 -0
- package/package.json +5 -1
- package/translation/index.d.ts +1 -1
- package/translation/lib/translation-loader.service.d.ts +20 -0
- package/translation/lib/translation.config.d.ts +19 -6
- package/translation/lib/translation.loader.d.ts +2 -2
- package/translation/lib/translation.parser.d.ts +7 -0
- package/translation/lib/translation.resolver.d.ts +9 -0
- package/translation/lib/translation.service.d.ts +12 -31
- package/translation/lib/translation.types.d.ts +8 -2
- package/translation/lib/translator.pipe.d.ts +0 -2
- package/types/README.md +2 -2
- package/utils/index.d.ts +6 -5
- package/utils/lib/execution.utils.d.ts +33 -0
- package/utils/lib/string.utils.d.ts +4 -0
- package/events/lib/event.type.d.ts +0 -5
- package/i18n/en/common.json +0 -191
- package/i18n/fa/common.json +0 -190
- package/utils/lib/string-util.d.ts +0 -6
- /package/date-time/lib/formatters/{time-duration-formatter.d.ts → time-duration.formatter.d.ts} +0 -0
- /package/date-time/lib/formatters/{timeleft-formatter.d.ts → timeleft.formatter.d.ts} +0 -0
- /package/format/lib/formatters/{number-formatter.d.ts → number.formatter.d.ts} +0 -0
- /package/format/lib/formatters/{string-formatter.d.ts → string.formatter.d.ts} +0 -0
- /package/utils/lib/{color-util.d.ts → color.utils.d.ts} +0 -0
- /package/utils/lib/{drawing-util.d.ts → drawing.utils.d.ts} +0 -0
- /package/utils/lib/{html-util.d.ts → html-utils.d.ts} +0 -0
- /package/utils/lib/{auto-unsubscribe.d.ts → lifecycle-helpers.utils.d.ts} +0 -0
@@ -1,8 +1,9 @@
|
|
1
1
|
import * as i0 from '@angular/core';
|
2
2
|
import { InjectionToken, inject, Injectable, Directive, Pipe, provideAppInitializer, NgModule } from '@angular/core';
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import {
|
3
|
+
import { of, shareReplay, firstValueFrom, BehaviorSubject, switchMap, from } from 'rxjs';
|
4
|
+
import { get } from 'lodash-es';
|
5
|
+
import { AXLocaleService } from '@acorex/core/locale';
|
6
|
+
import { waitFor } from '@acorex/core/utils';
|
6
7
|
|
7
8
|
const AX_TRANSLATION_CONFIG = new InjectionToken('AX_TRANSLATION_CONFIG', {
|
8
9
|
providedIn: 'root',
|
@@ -11,9 +12,17 @@ const AX_TRANSLATION_CONFIG = new InjectionToken('AX_TRANSLATION_CONFIG', {
|
|
11
12
|
},
|
12
13
|
});
|
13
14
|
const AXTranslationDefaultConfig = {
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
defaults: {
|
16
|
+
lang: 'en-US',
|
17
|
+
scope: 'common',
|
18
|
+
},
|
19
|
+
preload: {
|
20
|
+
langs: ['en-US'],
|
21
|
+
scopes: ['common'],
|
22
|
+
},
|
23
|
+
resolver: {
|
24
|
+
scopeKey: 'scope',
|
25
|
+
},
|
17
26
|
};
|
18
27
|
function translationConfig(config = {}) {
|
19
28
|
const result = {
|
@@ -24,7 +33,7 @@ function translationConfig(config = {}) {
|
|
24
33
|
}
|
25
34
|
|
26
35
|
class AXTranslationLoaderDefault {
|
27
|
-
|
36
|
+
load(options) {
|
28
37
|
return of({});
|
29
38
|
}
|
30
39
|
}
|
@@ -35,225 +44,256 @@ const AX_TRANSLATION_LOADER = new InjectionToken('AX_TRANSLATION_LOADER', {
|
|
35
44
|
},
|
36
45
|
});
|
37
46
|
|
38
|
-
|
39
|
-
function translateSync(key, options) {
|
40
|
-
return singletonInstance.translateSync(key, options);
|
41
|
-
}
|
42
|
-
class AXTranslationService {
|
43
|
-
getDefaultLang() {
|
44
|
-
return this.config.defaultLang;
|
45
|
-
}
|
46
|
-
getActiveLang() {
|
47
|
-
return this.activeLang.getValue();
|
48
|
-
}
|
49
|
-
setActiveLang(lang) {
|
50
|
-
if (lang != this.getActiveLang()) {
|
51
|
-
this.activeLang.next(lang);
|
52
|
-
this.eventService.emitEvent({
|
53
|
-
type: AXEventTypes.AXLanguageChanged,
|
54
|
-
payload: lang,
|
55
|
-
});
|
56
|
-
}
|
57
|
-
}
|
58
|
-
/**
|
59
|
-
* @ignore
|
60
|
-
*/
|
47
|
+
class AXTranslationLoaderService {
|
61
48
|
constructor() {
|
62
49
|
this.loader = inject(AX_TRANSLATION_LOADER);
|
63
50
|
this.config = inject(AX_TRANSLATION_CONFIG);
|
64
|
-
this.
|
65
|
-
this.
|
66
|
-
this.ongoingRequests = new Map();
|
67
|
-
this.activeLang = new BehaviorSubject(this.getDefaultLang());
|
68
|
-
this.langChanges$ = this.activeLang.asObservable();
|
69
|
-
this.expressionCache = new Map();
|
70
|
-
this.isExpression = (value) => value.includes('t(');
|
71
|
-
singletonInstance = this;
|
51
|
+
this.cache = new Map();
|
52
|
+
this.inflight = new Map();
|
72
53
|
}
|
73
|
-
|
74
|
-
const
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
}
|
79
|
-
// Use the new method to handle ongoing requests and loading
|
80
|
-
return this.fetchTranslationFiles(lang, scope);
|
81
|
-
}));
|
82
|
-
return forkJoin(requests);
|
83
|
-
}
|
84
|
-
fetchTranslationFiles(lang, scope) {
|
85
|
-
const requestKey = `${lang}_${scope}`;
|
86
|
-
// Return existing observable if the request is already in progress
|
87
|
-
if (this.ongoingRequests.has(requestKey)) {
|
88
|
-
return this.ongoingRequests.get(requestKey);
|
54
|
+
load(lang, scope) {
|
55
|
+
const key = `${lang}:${scope}`;
|
56
|
+
console.log('load', key);
|
57
|
+
if (this.cache.has(key)) {
|
58
|
+
return of(this.cache.get(key));
|
89
59
|
}
|
90
|
-
|
91
|
-
|
92
|
-
this.
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
60
|
+
if (!this.inflight.has(key)) {
|
61
|
+
const obs = this.loader.load({ lang, scope }).pipe(shareReplay(1));
|
62
|
+
this.inflight.set(key, obs);
|
63
|
+
obs.subscribe({
|
64
|
+
next: (data) => {
|
65
|
+
this.cache.set(key, data);
|
66
|
+
this.inflight.delete(key);
|
67
|
+
},
|
68
|
+
error: () => {
|
69
|
+
this.inflight.delete(key);
|
70
|
+
},
|
98
71
|
});
|
99
|
-
|
100
|
-
|
101
|
-
this.ongoingRequests.set(requestKey, translationObservable);
|
102
|
-
return translationObservable;
|
72
|
+
}
|
73
|
+
return this.inflight.get(key);
|
103
74
|
}
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
75
|
+
peek(lang, scope, key) {
|
76
|
+
const cacheKey = `${lang}:${scope}`;
|
77
|
+
const data = this.cache.get(cacheKey);
|
78
|
+
return get(data, key, null);
|
79
|
+
}
|
80
|
+
async preload(options) {
|
81
|
+
const langs = [...new Set(options?.langs ?? this.config.preload?.langs ?? [this.config.defaults.lang])];
|
82
|
+
const scopes = [...new Set(options?.scopes ?? this.config.preload?.scopes ?? [this.config.defaults.scope])];
|
83
|
+
const promises = [];
|
84
|
+
langs.forEach(lang => {
|
85
|
+
scopes.forEach(scope => {
|
86
|
+
const p = firstValueFrom(this.load(lang, scope));
|
87
|
+
promises.push(p);
|
88
|
+
});
|
89
|
+
});
|
90
|
+
await Promise.all(promises);
|
110
91
|
}
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
getTranslationFromCache(lang, scope, key) {
|
115
|
-
return get(this.translationCache, `${lang}.${scope}.${key}`, key);
|
92
|
+
clear() {
|
93
|
+
this.cache.clear();
|
94
|
+
this.inflight.clear();
|
116
95
|
}
|
117
|
-
|
118
|
-
return
|
96
|
+
getFallbackLangs(lang) {
|
97
|
+
return this.config.fallbacks?.langs?.[lang] ?? [];
|
119
98
|
}
|
120
|
-
|
121
|
-
|
122
|
-
this.loadLanguagesAndScopes([lang], [scope]).pipe(startWith()).subscribe({
|
123
|
-
error: (err) => {
|
124
|
-
this.handleError(`Error preloading translations for ${lang}, ${scope}`, err);
|
125
|
-
},
|
126
|
-
});
|
127
|
-
// Retrieve the translation from the cache or fallback to the key
|
128
|
-
let translation = this.getTranslationFromCache(lang, scope, key);
|
129
|
-
// Replace params like {{ name }}
|
130
|
-
if (params && typeof translation === 'string') {
|
131
|
-
Object.keys(params).forEach((paramKey) => {
|
132
|
-
translation = translation.replace(new RegExp(`{{\\s*${paramKey}\\s*}}`, 'g'), params[paramKey]);
|
133
|
-
});
|
134
|
-
}
|
135
|
-
return translation || key;
|
99
|
+
getFallbackScopes(scope) {
|
100
|
+
return this.config.fallbacks?.scopes?.[scope] ?? [];
|
136
101
|
}
|
137
|
-
|
138
|
-
|
139
|
-
|
102
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
103
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationLoaderService, providedIn: 'root' }); }
|
104
|
+
}
|
105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationLoaderService, decorators: [{
|
106
|
+
type: Injectable,
|
107
|
+
args: [{ providedIn: 'root' }]
|
108
|
+
}] });
|
109
|
+
|
110
|
+
class TranslationParserService {
|
111
|
+
constructor() {
|
112
|
+
this.legacyRegex = /t\(["']([^"']+)["']\s*(?:,\s*(\{.*?\}))?\)/g;
|
113
|
+
this.inlineRegex = /@([a-zA-Z\-]+:)?([a-zA-Z0-9_-]+):([a-zA-Z0-9_.:-]+)(?=[\\s.,;!?)]|$)/g;
|
114
|
+
}
|
115
|
+
isExpression(value) {
|
116
|
+
return typeof value === 'string' && (value.includes('t(') || value.includes('@'));
|
117
|
+
}
|
118
|
+
parse(expression, currentLang, currentScope) {
|
119
|
+
const tokens = [];
|
120
|
+
// Extract inline references like @lang:scope:key or @scope:key
|
121
|
+
let inlineMatch;
|
122
|
+
while ((inlineMatch = this.inlineRegex.exec(expression)) !== null) {
|
123
|
+
const langPart = inlineMatch[1]?.replace(':', '') ?? null;
|
124
|
+
const scope = inlineMatch[2] ?? currentScope;
|
125
|
+
const key = inlineMatch[3];
|
126
|
+
const fullMatch = inlineMatch[0];
|
127
|
+
tokens.push({ lang: langPart || currentLang, scope, key, fullMatch });
|
128
|
+
}
|
129
|
+
// Extract legacy expressions
|
130
|
+
let legacyMatch;
|
131
|
+
while ((legacyMatch = this.legacyRegex.exec(expression)) !== null) {
|
132
|
+
const key = legacyMatch[1];
|
133
|
+
const rawOptions = legacyMatch[2];
|
134
|
+
let scope = currentScope;
|
135
|
+
let lang = currentLang;
|
136
|
+
if (rawOptions) {
|
137
|
+
try {
|
138
|
+
const jsonString = rawOptions
|
139
|
+
.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?\s*:/g, '"$2":')
|
140
|
+
.replace(/'/g, '"');
|
141
|
+
const options = JSON.parse(jsonString);
|
142
|
+
scope = options.scope || scope;
|
143
|
+
lang = options.lang || lang;
|
144
|
+
}
|
145
|
+
catch (err) {
|
146
|
+
console.error('Invalid translation expression options:', err);
|
147
|
+
}
|
148
|
+
}
|
149
|
+
tokens.push({ key, scope, lang, fullMatch: legacyMatch[0] });
|
140
150
|
}
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
151
|
+
return tokens;
|
152
|
+
}
|
153
|
+
}
|
154
|
+
|
155
|
+
class TranslationResolverService {
|
156
|
+
constructor() {
|
157
|
+
this.loaderService = inject(AXTranslationLoaderService);
|
158
|
+
this.cache = new Map();
|
159
|
+
this.inflight = new Map();
|
160
|
+
this.parser = new TranslationParserService();
|
161
|
+
}
|
162
|
+
async resolve(lang, scope, key, params) {
|
163
|
+
const cacheKey = `${lang}:${scope}`;
|
164
|
+
// Load and cache if not present
|
165
|
+
if (!this.cache.has(cacheKey)) {
|
166
|
+
if (!this.inflight.has(cacheKey)) {
|
167
|
+
const fetchPromise = firstValueFrom(this.loaderService.load(lang, scope));
|
168
|
+
this.inflight.set(cacheKey, fetchPromise);
|
169
|
+
const data = await fetchPromise;
|
170
|
+
this.cache.set(cacheKey, data);
|
171
|
+
this.inflight.delete(cacheKey);
|
150
172
|
}
|
151
|
-
|
152
|
-
|
153
|
-
.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?\s*:/g, '"$2":') // Ensure keys are quoted
|
154
|
-
.replace(/'/g, '"'); // Replace single quotes with double quotes
|
155
|
-
const options = JSON.parse(jsonString);
|
156
|
-
matches.push({
|
157
|
-
key,
|
158
|
-
scope: options.scope || null,
|
159
|
-
lang: options.lang || null,
|
160
|
-
fullMatch: match[0],
|
161
|
-
});
|
173
|
+
else {
|
174
|
+
await this.inflight.get(cacheKey); // wait for the inflight fetch
|
162
175
|
}
|
163
|
-
|
164
|
-
|
165
|
-
|
176
|
+
}
|
177
|
+
const translations = this.cache.get(cacheKey);
|
178
|
+
let result = get(translations, key, key);
|
179
|
+
// Recursively resolve references
|
180
|
+
if (typeof result === 'string' && this.parser.isExpression(result)) {
|
181
|
+
const tokens = this.parser.parse(result, lang, scope);
|
182
|
+
if (tokens.length > 0) {
|
183
|
+
const first = tokens[0];
|
184
|
+
result = await this.resolve(first.lang || lang, first.scope || scope, first.key, params);
|
166
185
|
}
|
167
186
|
}
|
168
|
-
this.
|
169
|
-
|
187
|
+
return this.format(result, params);
|
188
|
+
}
|
189
|
+
format(text, params) {
|
190
|
+
if (!params || typeof text !== 'string')
|
191
|
+
return text;
|
192
|
+
return Object.keys(params).reduce((out, key) => {
|
193
|
+
const re = new RegExp(`{{\s*${key}\s*}}`, 'g');
|
194
|
+
return out.replace(re, params[key]);
|
195
|
+
}, text);
|
170
196
|
}
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
197
|
+
}
|
198
|
+
|
199
|
+
let singletonInstance;
|
200
|
+
function translateSync(key, options) {
|
201
|
+
return singletonInstance.translateSync(key, options);
|
202
|
+
}
|
203
|
+
class AXTranslationService {
|
204
|
+
constructor() {
|
205
|
+
this.localeService = inject(AXLocaleService);
|
206
|
+
this.config = inject(AX_TRANSLATION_CONFIG);
|
207
|
+
this.loader = inject(AXTranslationLoaderService);
|
208
|
+
this.parser = new TranslationParserService();
|
209
|
+
this.resolver = new TranslationResolverService();
|
210
|
+
this.activeLang = new BehaviorSubject('en-US');
|
211
|
+
this.langChanges$ = this.activeLang.asObservable();
|
212
|
+
singletonInstance = this;
|
213
|
+
this.localeService.profileChanged$.subscribe((locale) => {
|
214
|
+
if (locale?.localeInfo?.code) {
|
215
|
+
this.setActiveLang(locale.localeInfo.code);
|
216
|
+
}
|
176
217
|
});
|
177
218
|
}
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
if (!this.isExpression(text)) {
|
182
|
-
return this.loadLanguagesAndScopes([contextLang], [contextScope]).pipe(map(() => this.translateKey(text, contextLang, contextScope, params)), catchError((error) => {
|
183
|
-
this.handleError(`Error during translation:`, error);
|
184
|
-
return of(text); // Fallback to the original text
|
185
|
-
}));
|
219
|
+
setActiveLang(lang) {
|
220
|
+
if (lang && lang !== this.activeLang.getValue()) {
|
221
|
+
this.activeLang.next(lang);
|
186
222
|
}
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
const langs = Array.from(new Set(Array.from(langScopeSet).map((pair) => pair.split('_')[0])));
|
191
|
-
const scopes = Array.from(new Set(Array.from(langScopeSet).map((pair) => pair.split('_')[1])));
|
192
|
-
// Load all required languages and scopes
|
193
|
-
return this.loadLanguagesAndScopes(langs, scopes).pipe(map(() => {
|
194
|
-
// Resolve translations after loading
|
195
|
-
const translations = matches.reduce((acc, { key, scope, lang, fullMatch }) => {
|
196
|
-
const resolvedScope = scope || contextScope;
|
197
|
-
const resolvedLang = lang || contextLang;
|
198
|
-
acc[fullMatch] = this.translateKey(key, resolvedLang, resolvedScope, params);
|
199
|
-
return acc;
|
200
|
-
}, {});
|
201
|
-
// Replace all matches in the text with their resolved translations
|
202
|
-
return matches.reduce((result, { fullMatch }) => result.replace(new RegExp(fullMatch.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), translations[fullMatch]), text);
|
203
|
-
}), catchError((error) => {
|
204
|
-
this.handleError(`Error during translation:`, error);
|
205
|
-
return of(text); // Fallback to the original text
|
206
|
-
}));
|
223
|
+
}
|
224
|
+
getActiveLang() {
|
225
|
+
return this.activeLang.getValue();
|
207
226
|
}
|
208
227
|
translate$(text, options) {
|
209
|
-
if (
|
210
|
-
return
|
211
|
-
}
|
212
|
-
|
213
|
-
|
228
|
+
if (!text)
|
229
|
+
return of('');
|
230
|
+
const staticOptions = { ...options };
|
231
|
+
const staticScope = staticOptions.scope ?? this.config.defaults.scope;
|
232
|
+
return this.langChanges$.pipe(switchMap(lang => {
|
233
|
+
return from(this.translateAsync(text, {
|
234
|
+
...staticOptions,
|
235
|
+
lang: staticOptions.lang ?? lang,
|
236
|
+
scope: staticScope
|
237
|
+
}));
|
214
238
|
}));
|
215
239
|
}
|
216
240
|
async translateAsync(text, options) {
|
217
|
-
|
241
|
+
const lang = options?.lang ?? this.getActiveLang() ?? this.config.defaults.lang;
|
242
|
+
const scope = options?.scope ?? this.config.defaults.scope;
|
243
|
+
const params = options?.params;
|
244
|
+
if (!this.parser.isExpression(text)) {
|
245
|
+
const resolved = await this.resolver.resolve(lang, scope, text, params);
|
246
|
+
return this.resolver.format(resolved, params);
|
247
|
+
}
|
248
|
+
const tokens = this.parser.parse(text, lang, scope);
|
249
|
+
const results = await Promise.all(tokens.map(token => this.resolver.resolve(token.lang ?? lang, token.scope ?? scope, token.key, params)
|
250
|
+
.then(translated => [token.fullMatch, this.resolver.format(translated, params)])));
|
251
|
+
return results.reduce((output, [match, translated]) => output.replace(match, translated), text);
|
218
252
|
}
|
219
|
-
//#endregion
|
220
|
-
//#region Sync Translation Methods
|
221
253
|
translateSync(text, options) {
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
254
|
+
const lang = options?.lang ?? this.getActiveLang() ?? this.config.defaults.lang;
|
255
|
+
const scope = options?.scope ?? this.config.defaults.scope;
|
256
|
+
const params = options?.params;
|
257
|
+
const waitForLoad = options?.waitForLoad ?? false;
|
258
|
+
const timeoutMs = options?.timeoutMs ?? 100;
|
259
|
+
if (!this.parser.isExpression(text)) {
|
260
|
+
let translated = this.loader.peek(lang, scope, text);
|
261
|
+
if (!translated && waitForLoad) {
|
262
|
+
translated = waitFor(() => this.loader.peek(lang, scope, text), () => this.loader.load(lang, scope).subscribe(), timeoutMs);
|
263
|
+
}
|
264
|
+
return this.resolver.format(translated ?? text, params);
|
227
265
|
}
|
228
|
-
|
229
|
-
|
230
|
-
const
|
231
|
-
|
232
|
-
const
|
233
|
-
const
|
234
|
-
|
235
|
-
if (!
|
236
|
-
|
266
|
+
const tokens = this.parser.parse(text, lang, scope);
|
267
|
+
let result = text;
|
268
|
+
for (const token of tokens) {
|
269
|
+
const targetLang = token.lang ?? lang;
|
270
|
+
const targetScope = token.scope ?? scope;
|
271
|
+
const key = token.key;
|
272
|
+
let translation = this.loader.peek(targetLang, targetScope, key);
|
273
|
+
if (!translation) {
|
274
|
+
translation = waitFor(() => this.loader.peek(targetLang, targetScope, key), () => this.loader.load(targetLang, targetScope).subscribe(), waitForLoad ? timeoutMs : 0) ?? key;
|
237
275
|
}
|
238
|
-
|
239
|
-
}
|
240
|
-
|
241
|
-
return matches.reduce((result, { fullMatch }) => result.replace(fullMatch, translations[fullMatch]), text);
|
276
|
+
result = result.replace(token.fullMatch, this.resolver.format(translation, params));
|
277
|
+
}
|
278
|
+
return result;
|
242
279
|
}
|
243
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.
|
244
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.
|
280
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
281
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationService, providedIn: 'root' }); }
|
245
282
|
}
|
246
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.
|
283
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationService, decorators: [{
|
247
284
|
type: Injectable,
|
248
|
-
args: [{
|
285
|
+
args: [{
|
286
|
+
providedIn: 'root'
|
287
|
+
}]
|
249
288
|
}], ctorParameters: () => [] });
|
250
289
|
|
251
290
|
const loadTranslationScope = (route, state) => {
|
252
|
-
const
|
291
|
+
const translationLoaderService = inject(AXTranslationLoaderService);
|
292
|
+
const translationService = inject(AXTranslationService);
|
253
293
|
const config = inject(AX_TRANSLATION_CONFIG);
|
254
|
-
const scopeValue = route.data[config.
|
294
|
+
const scopeValue = route.data[config.resolver?.scopeKey];
|
255
295
|
const scopes = Array.isArray(scopeValue) ? scopeValue : [scopeValue];
|
256
|
-
return
|
296
|
+
return translationLoaderService.preload({ langs: [translationService.getActiveLang()], scopes });
|
257
297
|
};
|
258
298
|
|
259
299
|
class AXTranslatorDirective {
|
@@ -270,17 +310,17 @@ class AXTranslatorDirective {
|
|
270
310
|
},
|
271
311
|
});
|
272
312
|
}
|
273
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.
|
274
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.
|
313
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslatorDirective, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: AXTranslationService }], target: i0.ɵɵFactoryTarget.Directive }); }
|
314
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.8", type: AXTranslatorDirective, isStandalone: true, selector: "[translate]", ngImport: i0 }); }
|
275
315
|
}
|
276
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.
|
316
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslatorDirective, decorators: [{
|
277
317
|
type: Directive,
|
278
318
|
args: [{ selector: '[translate]' }]
|
279
319
|
}], ctorParameters: () => [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: AXTranslationService }] });
|
280
320
|
|
281
321
|
class AXTranslatorPipe {
|
282
|
-
constructor(
|
283
|
-
this.service =
|
322
|
+
constructor() {
|
323
|
+
this.service = inject(AXTranslationService);
|
284
324
|
}
|
285
325
|
transform(key, options) {
|
286
326
|
if (!key) {
|
@@ -288,40 +328,40 @@ class AXTranslatorPipe {
|
|
288
328
|
}
|
289
329
|
return this.service.translate$(key, options);
|
290
330
|
}
|
291
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.
|
292
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.
|
331
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslatorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
332
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.8", ngImport: i0, type: AXTranslatorPipe, isStandalone: true, name: "translate" }); }
|
293
333
|
}
|
294
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.
|
334
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslatorPipe, decorators: [{
|
295
335
|
type: Pipe,
|
296
336
|
args: [{
|
297
337
|
name: 'translate',
|
298
338
|
pure: true,
|
299
339
|
}]
|
300
|
-
}]
|
340
|
+
}] });
|
301
341
|
|
302
|
-
function initializeApp(translatorService
|
342
|
+
function initializeApp(translatorService) {
|
303
343
|
return () => {
|
304
|
-
return translatorService.
|
344
|
+
return translatorService.preload();
|
305
345
|
};
|
306
346
|
}
|
307
347
|
class AXTranslationModule {
|
308
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.
|
309
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.
|
310
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.
|
348
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
349
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationModule, imports: [AXTranslatorPipe, AXTranslatorDirective], exports: [AXTranslatorPipe, AXTranslatorDirective] }); }
|
350
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationModule, providers: [
|
311
351
|
provideAppInitializer(() => {
|
312
|
-
const initializerFn = initializeApp(inject(
|
352
|
+
const initializerFn = initializeApp(inject(AXTranslationLoaderService));
|
313
353
|
return initializerFn();
|
314
354
|
}),
|
315
355
|
] }); }
|
316
356
|
}
|
317
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.
|
357
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.8", ngImport: i0, type: AXTranslationModule, decorators: [{
|
318
358
|
type: NgModule,
|
319
359
|
args: [{
|
320
360
|
imports: [AXTranslatorPipe, AXTranslatorDirective],
|
321
361
|
exports: [AXTranslatorPipe, AXTranslatorDirective],
|
322
362
|
providers: [
|
323
363
|
provideAppInitializer(() => {
|
324
|
-
const initializerFn = initializeApp(inject(
|
364
|
+
const initializerFn = initializeApp(inject(AXTranslationLoaderService));
|
325
365
|
return initializerFn();
|
326
366
|
}),
|
327
367
|
],
|