@seliseblocks/blocks-angular-localization 0.0.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/dist/index.d.ts
ADDED
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, Signal, PipeTransform, TemplateRef } from '@angular/core';
|
|
3
|
+
import { Subject, Observable } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Controls how translations are loaded at application startup.
|
|
7
|
+
*
|
|
8
|
+
* - `'modular'` — Lazy per-route loading via `provideUilmScope()`.
|
|
9
|
+
* Shows empty placeholders while fetching. Best for large apps
|
|
10
|
+
* with many modules where loading everything upfront is wasteful.
|
|
11
|
+
*
|
|
12
|
+
* - `'eager'` — All modules listed in `preloadModules` are fetched
|
|
13
|
+
* before the app renders. Blocks bootstrap via `APP_INITIALIZER`.
|
|
14
|
+
* Best for smaller apps or when avoiding placeholder flicker matters.
|
|
15
|
+
*/
|
|
16
|
+
type UilmLoadingStrategy = 'modular' | 'eager';
|
|
17
|
+
/**
|
|
18
|
+
* Controls where translations are persisted.
|
|
19
|
+
*
|
|
20
|
+
* - `'memory'` — In-memory cache only (cleared on page reload).
|
|
21
|
+
* - `'indexeddb'` — Persists to IndexedDB alongside in-memory cache.
|
|
22
|
+
* Translations load instantly from disk on subsequent visits while
|
|
23
|
+
* the in-memory L1 cache provides zero-latency lookups within a session.
|
|
24
|
+
*/
|
|
25
|
+
type UilmCacheStorage = 'memory' | 'indexeddb';
|
|
26
|
+
/**
|
|
27
|
+
* Controls where the active language preference is persisted.
|
|
28
|
+
*
|
|
29
|
+
* - `'localStorage'` — Persists across browser sessions (default).
|
|
30
|
+
* - `'sessionStorage'` — Persists only for the current tab/session.
|
|
31
|
+
* - `'none'` — No persistence; always starts with `defaultLang`.
|
|
32
|
+
*/
|
|
33
|
+
type UilmLangStorage = 'localStorage' | 'sessionStorage' | 'none';
|
|
34
|
+
/** A module entry: plain string or an object with an optional alias. */
|
|
35
|
+
type UilmModuleEntry = string | {
|
|
36
|
+
module: string;
|
|
37
|
+
alias?: string;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Root configuration for the blocks-localization library.
|
|
41
|
+
*
|
|
42
|
+
* @publicApi
|
|
43
|
+
*/
|
|
44
|
+
interface BlocksLocalizationConfig {
|
|
45
|
+
/** UILM API base URL, e.g. `'https://api.seliseblocks.com/uilm/v1'` */
|
|
46
|
+
uilmApiBaseUrl: string;
|
|
47
|
+
/** Project key sent as `x-blocks-key` header. */
|
|
48
|
+
projectKey: string;
|
|
49
|
+
/** Optional Bearer token for authenticated UILM access. */
|
|
50
|
+
accessToken?: string;
|
|
51
|
+
/** Short language codes, e.g. `['en', 'de', 'fr', 'it']`. */
|
|
52
|
+
availableLangs: readonly string[];
|
|
53
|
+
/** Default language short code, e.g. `'en'`. */
|
|
54
|
+
defaultLang: string;
|
|
55
|
+
/** Maps short codes → full locale codes, e.g. `{ en: 'en-US', de: 'de-DE' }`. */
|
|
56
|
+
localeMapping?: Readonly<Record<string, string>>;
|
|
57
|
+
/**
|
|
58
|
+
* Cache TTL in milliseconds. `0` means no expiry — cached translations are served
|
|
59
|
+
* until explicitly cleared or the session ends (memory) / storage is cleared (IndexedDB).
|
|
60
|
+
* @defaultValue `0`
|
|
61
|
+
*/
|
|
62
|
+
cacheTimeout?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Where to persist the translation cache.
|
|
65
|
+
*
|
|
66
|
+
* - `'memory'` — In-memory only (default, current behavior).
|
|
67
|
+
* - `'indexeddb'` — Persists to IndexedDB. Translations survive page reloads
|
|
68
|
+
* and are available instantly on subsequent visits. In-memory cache still
|
|
69
|
+
* serves as L1 for zero-latency lookups within the same session.
|
|
70
|
+
*
|
|
71
|
+
* @defaultValue `'memory'`
|
|
72
|
+
*/
|
|
73
|
+
cacheStorage?: UilmCacheStorage;
|
|
74
|
+
/**
|
|
75
|
+
* When `cacheStorage` is `'indexeddb'` and a cached entry exists, serve
|
|
76
|
+
* it immediately and revalidate from the API in the background.
|
|
77
|
+
* Updated translations are merged into the store silently without blocking the UI.
|
|
78
|
+
* Has no effect when `cacheStorage` is `'memory'`.
|
|
79
|
+
* @defaultValue `false`
|
|
80
|
+
*/
|
|
81
|
+
revalidateInBackground?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Prefix translation keys with the module name/alias
|
|
84
|
+
* (e.g. `"dashboard.LABEL.HELLO"`).
|
|
85
|
+
* @defaultValue `false`
|
|
86
|
+
*/
|
|
87
|
+
prefixKeysWithModule?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Enable production mode (suppresses console warnings).
|
|
90
|
+
* @defaultValue `false`
|
|
91
|
+
*/
|
|
92
|
+
prodMode?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Fall back to local JSON files when the UILM API request fails.
|
|
95
|
+
*
|
|
96
|
+
* Local files are expected at `{localAssetsPath}/{moduleName}/{lang}.json`
|
|
97
|
+
* (nested JSON is flattened to dot-notation keys automatically).
|
|
98
|
+
* For modules with an empty-string alias (e.g. `common`), the path is
|
|
99
|
+
* `{localAssetsPath}/{lang}.json`.
|
|
100
|
+
*
|
|
101
|
+
* @defaultValue `true`
|
|
102
|
+
*/
|
|
103
|
+
fallbackToLocal?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Base path for local fallback JSON files (relative to the app's public root).
|
|
106
|
+
* @defaultValue `'assets/i18n'`
|
|
107
|
+
*/
|
|
108
|
+
localAssetsPath?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Where to persist the active language preference.
|
|
111
|
+
*
|
|
112
|
+
* - `'localStorage'` — Persists across browser sessions (default).
|
|
113
|
+
* - `'sessionStorage'` — Persists only for the current tab/session.
|
|
114
|
+
* - `'none'` — No persistence; always starts with `defaultLang`.
|
|
115
|
+
*
|
|
116
|
+
* The storage key used is `uilmLang` (or custom via `langStorageKey`).
|
|
117
|
+
*
|
|
118
|
+
* @defaultValue `'localStorage'`
|
|
119
|
+
*/
|
|
120
|
+
langStorage?: UilmLangStorage;
|
|
121
|
+
/**
|
|
122
|
+
* Custom storage key for persisting the active language.
|
|
123
|
+
* @defaultValue `'uilmLang'`
|
|
124
|
+
*/
|
|
125
|
+
langStorageKey?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Translation loading strategy.
|
|
128
|
+
*
|
|
129
|
+
* - `'modular'` — lazy per-route loading, empty placeholders while fetching
|
|
130
|
+
* - `'eager'` — all `preloadModules` fetched on startup, blocks rendering until ready
|
|
131
|
+
*
|
|
132
|
+
* @defaultValue `'modular'`
|
|
133
|
+
*/
|
|
134
|
+
strategy?: UilmLoadingStrategy;
|
|
135
|
+
/**
|
|
136
|
+
* Modules to preload at app startup (before any route loads).
|
|
137
|
+
*
|
|
138
|
+
* In `'modular'` mode these are loaded alongside route-level modules.
|
|
139
|
+
* In `'eager'` mode these should include **all** module scopes — route-level
|
|
140
|
+
* `provideUilmScope()` calls will skip fetching if translations are already cached.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* preloadModules: ['common', { module: 'shared', alias: 'sh' }]
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
preloadModules?: UilmModuleEntry[];
|
|
148
|
+
}
|
|
149
|
+
/** Language entity returned by the UILM API. */
|
|
150
|
+
interface UilmLanguage {
|
|
151
|
+
itemId: string;
|
|
152
|
+
languageName: string;
|
|
153
|
+
languageCode: string;
|
|
154
|
+
isDefault: boolean;
|
|
155
|
+
projectKey: string | null;
|
|
156
|
+
}
|
|
157
|
+
/** Module entity returned by the UILM API. */
|
|
158
|
+
interface UilmModule {
|
|
159
|
+
moduleName: string;
|
|
160
|
+
name: string | null;
|
|
161
|
+
itemId: string;
|
|
162
|
+
createDate: string;
|
|
163
|
+
lastUpdateDate: string;
|
|
164
|
+
createdBy: string | null;
|
|
165
|
+
lastUpdatedBy: string | null;
|
|
166
|
+
tenantId: string | null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Provides all UILM translation infrastructure for an Angular application.
|
|
171
|
+
*
|
|
172
|
+
* ## Strategies
|
|
173
|
+
*
|
|
174
|
+
* ### `'modular'` (default)
|
|
175
|
+
* Preloads only the modules listed in `preloadModules` at startup.
|
|
176
|
+
* Additional modules are lazily loaded per route via `provideUilmScope()`.
|
|
177
|
+
* Shows empty placeholders while translations are loading.
|
|
178
|
+
*
|
|
179
|
+
* ### `'eager'`
|
|
180
|
+
* All modules in `preloadModules` are fetched at startup (non-blocking).
|
|
181
|
+
* Use `UilmLoadingScreenComponent` with `UilmStore.ready` to gate the UI
|
|
182
|
+
* until translations are available. Route-level `provideUilmScope()` calls
|
|
183
|
+
* become cache hits.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* // Eager — all modules upfront with loading screen
|
|
188
|
+
* provideBlocksLocalization({
|
|
189
|
+
* strategy: 'eager',
|
|
190
|
+
* preloadModules: [
|
|
191
|
+
* { module: 'common', alias: '' },
|
|
192
|
+
* 'dashboard',
|
|
193
|
+
* { module: 'opportunity', alias: 'op' },
|
|
194
|
+
* ],
|
|
195
|
+
* // ...
|
|
196
|
+
* })
|
|
197
|
+
*
|
|
198
|
+
* // app.component.html
|
|
199
|
+
* // @if (!store.ready()) {
|
|
200
|
+
* // <uilm-loading-screen />
|
|
201
|
+
* // } @else {
|
|
202
|
+
* // <router-outlet />
|
|
203
|
+
* // }
|
|
204
|
+
* ```
|
|
205
|
+
*
|
|
206
|
+
* @publicApi
|
|
207
|
+
*/
|
|
208
|
+
declare function provideBlocksLocalization(config: BlocksLocalizationConfig): i0.EnvironmentProviders;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Injection token for the blocks-localization configuration.
|
|
212
|
+
* Provided by `provideBlocksLocalization()` at the application root.
|
|
213
|
+
*/
|
|
214
|
+
declare const BLOCKS_LOCALIZATION_CONFIG: InjectionToken<BlocksLocalizationConfig>;
|
|
215
|
+
|
|
216
|
+
/** Flat key → value translation map. */
|
|
217
|
+
type TranslationMap = Record<string, string>;
|
|
218
|
+
/**
|
|
219
|
+
* Core reactive translation store.
|
|
220
|
+
*
|
|
221
|
+
* Holds translations per language, tracks the active language via signals,
|
|
222
|
+
* and persists language preference to `localStorage`.
|
|
223
|
+
*
|
|
224
|
+
* @publicApi
|
|
225
|
+
*/
|
|
226
|
+
declare class UilmStore {
|
|
227
|
+
private readonly config;
|
|
228
|
+
private readonly destroyRef;
|
|
229
|
+
private readonly storageKey;
|
|
230
|
+
/** Internal translation maps: `lang → flat key-value pairs` */
|
|
231
|
+
private readonly store;
|
|
232
|
+
/** Toggled on every `setTranslation` call to trigger signal reactivity. */
|
|
233
|
+
private readonly _version;
|
|
234
|
+
private versionCounter;
|
|
235
|
+
/** Active language short code. */
|
|
236
|
+
readonly activeLang: i0.WritableSignal<string>;
|
|
237
|
+
/**
|
|
238
|
+
* When `true`, `translate()` returns the raw key instead of the translated value.
|
|
239
|
+
* Toggled via `window.postMessage({ action: 'keymode', keymode: true/false })`.
|
|
240
|
+
* Useful for testing with a browser extension.
|
|
241
|
+
*/
|
|
242
|
+
readonly keyMode: i0.WritableSignal<boolean>;
|
|
243
|
+
/** Read-only version signal — depend on this to react to translation changes. */
|
|
244
|
+
readonly version: i0.Signal<number>;
|
|
245
|
+
/** `true` when translations have been loaded for the active language. */
|
|
246
|
+
readonly ready: i0.Signal<boolean>;
|
|
247
|
+
constructor();
|
|
248
|
+
/**
|
|
249
|
+
* Translate a key for the active language.
|
|
250
|
+
* Supports interpolation: `{{ name }}` in values is replaced by `params.name`.
|
|
251
|
+
*
|
|
252
|
+
* Returns the raw key if no translation is found.
|
|
253
|
+
*/
|
|
254
|
+
translate(key: string, params?: Record<string, unknown>): string;
|
|
255
|
+
/** Check if a translation key exists for the active language. */
|
|
256
|
+
has(key: string): boolean;
|
|
257
|
+
/** Merge translations into the store for a given language. */
|
|
258
|
+
setTranslation(data: TranslationMap, lang: string): void;
|
|
259
|
+
/** Set active language and persist to `localStorage`. Ignores invalid language codes. */
|
|
260
|
+
setActiveLang(lang: string): void;
|
|
261
|
+
/** Get configured available languages. */
|
|
262
|
+
getAvailableLangs(): string[];
|
|
263
|
+
private getStorage;
|
|
264
|
+
private loadPersistedLang;
|
|
265
|
+
private persistLang;
|
|
266
|
+
/**
|
|
267
|
+
* Listen for `window.postMessage` events to toggle key mode.
|
|
268
|
+
*
|
|
269
|
+
* Expected payload: `{ action: 'keymode', keymode: boolean }`
|
|
270
|
+
*
|
|
271
|
+
* Only messages from the same window and origin are accepted.
|
|
272
|
+
* Toggling key mode bumps the version signal so all translated
|
|
273
|
+
* values reactively update across the UI.
|
|
274
|
+
*/
|
|
275
|
+
private listenForKeyModeToggle;
|
|
276
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UilmStore, never>;
|
|
277
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<UilmStore>;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* IndexedDB persistence layer for UILM translation cache.
|
|
282
|
+
*
|
|
283
|
+
* Stores translation maps keyed by `{prefix}::{lang}` with timestamps
|
|
284
|
+
* for TTL-based invalidation. Falls back gracefully to `null` when
|
|
285
|
+
* IndexedDB is unavailable (SSR, restrictive incognito, etc.).
|
|
286
|
+
*
|
|
287
|
+
* All public methods are **fire-and-forget safe** — they never throw
|
|
288
|
+
* and resolve to `null` / `void` on any failure.
|
|
289
|
+
*
|
|
290
|
+
* @publicApi
|
|
291
|
+
*/
|
|
292
|
+
declare class UilmIndexedDbCache {
|
|
293
|
+
private dbReady;
|
|
294
|
+
constructor();
|
|
295
|
+
/** Re-open the database connection (used after unexpected close). */
|
|
296
|
+
private reconnect;
|
|
297
|
+
/**
|
|
298
|
+
* Retrieve a cached entry if it exists and hasn't exceeded the TTL.
|
|
299
|
+
*
|
|
300
|
+
* @param key Cache key (`{prefix}::{lang}`)
|
|
301
|
+
* @param ttl Time-to-live in ms. `0` disables expiry (entry is always valid).
|
|
302
|
+
* @returns The translation map, or `null` on miss / expiry / error.
|
|
303
|
+
*/
|
|
304
|
+
get(key: string, ttl: number): Promise<TranslationMap | null>;
|
|
305
|
+
/**
|
|
306
|
+
* Retrieve a stale entry (ignoring TTL) for fallback purposes.
|
|
307
|
+
*
|
|
308
|
+
* @param key Cache key
|
|
309
|
+
* @returns The translation map regardless of age, or `null` if absent.
|
|
310
|
+
*/
|
|
311
|
+
getStale(key: string): Promise<TranslationMap | null>;
|
|
312
|
+
/**
|
|
313
|
+
* Persist a translation map.
|
|
314
|
+
*
|
|
315
|
+
* @param key Cache key
|
|
316
|
+
* @param data Flat key→value translation map
|
|
317
|
+
*/
|
|
318
|
+
set(key: string, data: TranslationMap): Promise<void>;
|
|
319
|
+
/** Remove all cached translations from IndexedDB. */
|
|
320
|
+
clear(): Promise<void>;
|
|
321
|
+
private openDb;
|
|
322
|
+
private txGet;
|
|
323
|
+
private txPut;
|
|
324
|
+
private txClear;
|
|
325
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UilmIndexedDbCache, never>;
|
|
326
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<UilmIndexedDbCache>;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Low-level HTTP client for fetching translations from the UILM API.
|
|
331
|
+
*
|
|
332
|
+
* ## Caching architecture (two-tier)
|
|
333
|
+
*
|
|
334
|
+
* | Layer | Storage | Lifetime | When enabled |
|
|
335
|
+
* |-------|-----------------|-----------------|---------------------------|
|
|
336
|
+
* | L1 | In-memory `Map` | Current session | Always |
|
|
337
|
+
* | L2 | IndexedDB | Cross-session | `cacheStorage: 'indexeddb'`|
|
|
338
|
+
*
|
|
339
|
+
* ### Lookup order
|
|
340
|
+
* 1. **L1 hit** (valid TTL) → return immediately
|
|
341
|
+
* 2. **In-flight dedup** → share existing Observable
|
|
342
|
+
* 3. **L2 hit** (valid TTL, if enabled) → populate L1, return
|
|
343
|
+
* 4. **HTTP fetch** → populate L1 + L2, return
|
|
344
|
+
* 5. **Error fallback chain**: stale L1 → stale L2 → local JSON → empty `{}`
|
|
345
|
+
*
|
|
346
|
+
* @publicApi
|
|
347
|
+
*/
|
|
348
|
+
declare class UilmLoader {
|
|
349
|
+
private readonly http;
|
|
350
|
+
private readonly config;
|
|
351
|
+
private readonly idbCache;
|
|
352
|
+
private readonly destroyRef;
|
|
353
|
+
/** L1 in-memory cache. */
|
|
354
|
+
private readonly memCache;
|
|
355
|
+
/** Tracks in-flight HTTP observables for request deduplication. */
|
|
356
|
+
private readonly inflight;
|
|
357
|
+
/** Emits when a background revalidation produces updated translations. */
|
|
358
|
+
readonly revalidated$: Subject<{
|
|
359
|
+
lang: string;
|
|
360
|
+
data: TranslationMap;
|
|
361
|
+
}>;
|
|
362
|
+
private availableModules;
|
|
363
|
+
private availableLanguages;
|
|
364
|
+
private shortToFullMapping;
|
|
365
|
+
private modulesLoaded;
|
|
366
|
+
private languagesLoaded;
|
|
367
|
+
private metadataInflight$;
|
|
368
|
+
constructor();
|
|
369
|
+
private get cacheTimeout();
|
|
370
|
+
private get shouldPrefixKeys();
|
|
371
|
+
private get useIndexedDb();
|
|
372
|
+
private get shouldRevalidate();
|
|
373
|
+
private get shouldFallbackToLocal();
|
|
374
|
+
private get localAssetsPath();
|
|
375
|
+
/**
|
|
376
|
+
* Fetch a single UILM module's translations.
|
|
377
|
+
*
|
|
378
|
+
* @param lang Short language code (e.g. `'en'`)
|
|
379
|
+
* @param moduleName UILM module name as registered in the API
|
|
380
|
+
* @param alias Optional alias used as the key prefix instead of the module name
|
|
381
|
+
* @returns Observable emitting the (optionally prefixed) key→value map
|
|
382
|
+
*/
|
|
383
|
+
fetchModuleTranslations(lang: string, moduleName: string, alias?: string): Observable<TranslationMap>;
|
|
384
|
+
/**
|
|
385
|
+
* Attempt to load translations from IndexedDB cache only (no API, no metadata).
|
|
386
|
+
* Returns `null` if IndexedDB is disabled or the entry is missing.
|
|
387
|
+
* Used for instant store hydration before metadata is available.
|
|
388
|
+
*/
|
|
389
|
+
loadFromCacheOnly(lang: string, moduleName: string, alias?: string): Observable<TranslationMap | null>;
|
|
390
|
+
/** Ensure modules and languages metadata are loaded (fetches once, then no-ops). */
|
|
391
|
+
ensureMetadataLoaded(): Observable<void>;
|
|
392
|
+
/** Clear all translation caches (L1 in-memory, in-flight, and L2 IndexedDB if enabled). */
|
|
393
|
+
clearCache(): void;
|
|
394
|
+
/** Fetch available languages from the UILM API. */
|
|
395
|
+
getAvailableLanguages(): Observable<UilmLanguage[]>;
|
|
396
|
+
/** Fetch available modules from the UILM API. */
|
|
397
|
+
getAvailableModules(): Observable<UilmModule[]>;
|
|
398
|
+
/** Get cached languages (empty until `ensureMetadataLoaded()` resolves). */
|
|
399
|
+
getLanguages(): UilmLanguage[];
|
|
400
|
+
/** Get cached modules (empty until `ensureMetadataLoaded()` resolves). */
|
|
401
|
+
getModules(): UilmModule[];
|
|
402
|
+
private buildCacheKey;
|
|
403
|
+
/** Check whether the L1 entry is present and within TTL. `cacheTimeout=0` means no expiry. */
|
|
404
|
+
private isL1Valid;
|
|
405
|
+
/** Write data to L1 (always) and L2 (when enabled). */
|
|
406
|
+
private populateCache;
|
|
407
|
+
/**
|
|
408
|
+
* Resolve translations through the full L2 → HTTP → fallback chain.
|
|
409
|
+
* Called only when L1 misses and no in-flight request exists.
|
|
410
|
+
*/
|
|
411
|
+
private resolveTranslation;
|
|
412
|
+
/** Issue the HTTP request and handle success / error with full fallback chain. */
|
|
413
|
+
private fetchFromApi;
|
|
414
|
+
/**
|
|
415
|
+
* Fallback chain on HTTP failure:
|
|
416
|
+
* 1. Stale L1 (in-memory)
|
|
417
|
+
* 2. Stale L2 (IndexedDB, if enabled)
|
|
418
|
+
* 3. Local JSON file (if enabled)
|
|
419
|
+
* 4. Empty map
|
|
420
|
+
*/
|
|
421
|
+
private resolveFromFallbacks;
|
|
422
|
+
/** Attempt local JSON fallback, or return empty map. */
|
|
423
|
+
private localFallbackOrEmpty;
|
|
424
|
+
/**
|
|
425
|
+
* Fetch translations from a local JSON file.
|
|
426
|
+
* Nested JSON is automatically flattened to dot-notation keys.
|
|
427
|
+
*
|
|
428
|
+
* Path convention:
|
|
429
|
+
* - Module with content: `{localAssetsPath}/{moduleName}/{lang}.json`
|
|
430
|
+
* - Root/common module (empty alias): `{localAssetsPath}/{lang}.json`
|
|
431
|
+
*/
|
|
432
|
+
private fetchLocalFallback;
|
|
433
|
+
/**
|
|
434
|
+
* Fire-and-forget API fetch that silently updates caches and emits on
|
|
435
|
+
* `revalidated$` when the response differs from the currently cached data.
|
|
436
|
+
*/
|
|
437
|
+
private revalidateFromApi;
|
|
438
|
+
private buildHeaders;
|
|
439
|
+
/** Ensure API response is a valid flat object. Returns empty map for malformed responses. */
|
|
440
|
+
private sanitizeApiResponse;
|
|
441
|
+
/** Shallow key-by-key equality check for flat TranslationMaps. */
|
|
442
|
+
private shallowEqual;
|
|
443
|
+
private prefixKeys;
|
|
444
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UilmLoader, never>;
|
|
445
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<UilmLoader>;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
interface UilmScopeConfig {
|
|
449
|
+
/**
|
|
450
|
+
* UILM modules to load for this route.
|
|
451
|
+
*
|
|
452
|
+
* Each entry can be:
|
|
453
|
+
* - A plain string (module name, used as-is for prefixing)
|
|
454
|
+
* - An object `{ module: string, alias?: string }` to remap the prefix
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```typescript
|
|
458
|
+
* provideUilmScope({
|
|
459
|
+
* modules: [
|
|
460
|
+
* 'dashboard',
|
|
461
|
+
* { module: 'opportunity', alias: 'op' },
|
|
462
|
+
* { module: 'backend', alias: 'be' },
|
|
463
|
+
* ],
|
|
464
|
+
* })
|
|
465
|
+
* ```
|
|
466
|
+
*/
|
|
467
|
+
modules: UilmModuleEntry[];
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Route-level provider that lazily loads specific UILM modules on navigation.
|
|
471
|
+
*
|
|
472
|
+
* In `'eager'` strategy mode, translations are typically already cached
|
|
473
|
+
* from the initial `APP_INITIALIZER` load. The loader's cache deduplication
|
|
474
|
+
* ensures no redundant HTTP calls are made.
|
|
475
|
+
*
|
|
476
|
+
* Re-fetches automatically when the active language changes.
|
|
477
|
+
* Subscriptions are auto-cleaned via `DestroyRef`.
|
|
478
|
+
*
|
|
479
|
+
* @publicApi
|
|
480
|
+
*/
|
|
481
|
+
declare function provideUilmScope(config: UilmScopeConfig): i0.EnvironmentProviders;
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Headless language switching service.
|
|
485
|
+
* Provides programmatic control over the active language.
|
|
486
|
+
*/
|
|
487
|
+
declare class BlocksLangSwitcher {
|
|
488
|
+
private readonly store;
|
|
489
|
+
private readonly loader;
|
|
490
|
+
/** Active language as a signal. */
|
|
491
|
+
readonly activeLang: Signal<string>;
|
|
492
|
+
/** Get the currently active short language code. */
|
|
493
|
+
getActiveLang(): string;
|
|
494
|
+
/** Get the list of configured available language codes. */
|
|
495
|
+
getAvailableLangs(): string[];
|
|
496
|
+
/**
|
|
497
|
+
* Switch the active language.
|
|
498
|
+
* @param lang Short language code (e.g. 'en', 'de')
|
|
499
|
+
* @param reload Whether to reload the page after switching. Default: false
|
|
500
|
+
*/
|
|
501
|
+
setActiveLang(lang: string, reload?: boolean): void;
|
|
502
|
+
/** Fetch available languages from the UILM API. */
|
|
503
|
+
getAvailableLanguagesFromApi(): Observable<UilmLanguage[]>;
|
|
504
|
+
/** Clear the translation cache. */
|
|
505
|
+
clearCache(): void;
|
|
506
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BlocksLangSwitcher, never>;
|
|
507
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<BlocksLangSwitcher>;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Structural directive that provides a translation function to the template.
|
|
512
|
+
* Re-renders when the active language or translations change.
|
|
513
|
+
*
|
|
514
|
+
* @example
|
|
515
|
+
* ```html
|
|
516
|
+
* <section *uilmTranslate="let t">
|
|
517
|
+
* <p>{{ t('dashboard.LABEL.TITLE') }}</p>
|
|
518
|
+
* </section>
|
|
519
|
+
* ```
|
|
520
|
+
*
|
|
521
|
+
* With scope (auto-prefixes keys):
|
|
522
|
+
* ```html
|
|
523
|
+
* <section *uilmTranslate="let t; scope: 'dashboard'">
|
|
524
|
+
* <p>{{ t('LABEL.TITLE') }}</p> <!-- resolves to dashboard.LABEL.TITLE -->
|
|
525
|
+
* </section>
|
|
526
|
+
* ```
|
|
527
|
+
*/
|
|
528
|
+
declare class UilmTranslateDirective {
|
|
529
|
+
private readonly store;
|
|
530
|
+
private readonly templateRef;
|
|
531
|
+
private readonly vcr;
|
|
532
|
+
private viewRef;
|
|
533
|
+
/** Optional scope prefix */
|
|
534
|
+
readonly uilmTranslateScope: i0.InputSignal<string>;
|
|
535
|
+
constructor();
|
|
536
|
+
private ensureView;
|
|
537
|
+
static ngTemplateContextGuard(_dir: UilmTranslateDirective, _ctx: unknown): _ctx is UilmTranslateContext;
|
|
538
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UilmTranslateDirective, never>;
|
|
539
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<UilmTranslateDirective, "[uilmTranslate]", never, { "uilmTranslateScope": { "alias": "uilmTranslateScope"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
540
|
+
}
|
|
541
|
+
interface UilmTranslateContext {
|
|
542
|
+
$implicit: (key: string, params?: Record<string, unknown>) => string;
|
|
543
|
+
uilmTranslate: (key: string, params?: Record<string, unknown>) => string;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Resolves a multilingual object to the value matching the current active language.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```html
|
|
551
|
+
* <!-- Given: { en: 'Hello', de: 'Hallo', fr: 'Bonjour' } -->
|
|
552
|
+
* {{ item.name | multiLang }} <!-- outputs 'Hello' when lang is 'en' -->
|
|
553
|
+
* ```
|
|
554
|
+
*/
|
|
555
|
+
declare class MultiLangPipe implements PipeTransform {
|
|
556
|
+
private readonly store;
|
|
557
|
+
transform(value: Record<string, string> | string | null | undefined): string;
|
|
558
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MultiLangPipe, never>;
|
|
559
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<MultiLangPipe, "multiLang", true>;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Impure pipe that translates a key using the UILM store.
|
|
564
|
+
* Re-evaluates when the active language or translations change.
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* ```html
|
|
568
|
+
* <p>{{ 'dashboard.LABEL.TITLE' | uilmTranslate }}</p>
|
|
569
|
+
* <p>{{ 'LABEL.HELLO' | uilmTranslate: { name: userName } }}</p>
|
|
570
|
+
* ```
|
|
571
|
+
*/
|
|
572
|
+
declare class UilmTranslatePipe implements PipeTransform {
|
|
573
|
+
private readonly store;
|
|
574
|
+
private lastKey;
|
|
575
|
+
private lastLang;
|
|
576
|
+
private lastVersion;
|
|
577
|
+
private lastParamsJson;
|
|
578
|
+
private lastValue;
|
|
579
|
+
transform(key: string, params?: Record<string, unknown>): string;
|
|
580
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UilmTranslatePipe, never>;
|
|
581
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<UilmTranslatePipe, "uilmTranslate", true>;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Translation service for component classes.
|
|
586
|
+
* Fully signal-based with sync helpers.
|
|
587
|
+
*
|
|
588
|
+
* @example
|
|
589
|
+
* ```typescript
|
|
590
|
+
* private readonly uilm = inject(UilmTranslateService);
|
|
591
|
+
*
|
|
592
|
+
* // Signal-based (reactive, updates on lang change + translation load)
|
|
593
|
+
* title = this.uilm.t('dashboard.LABEL.TITLE');
|
|
594
|
+
* // In template: {{ title() }}
|
|
595
|
+
*
|
|
596
|
+
* // Sync snapshot (does NOT react)
|
|
597
|
+
* label = this.uilm.translate('dashboard.LABEL.TITLE');
|
|
598
|
+
* ```
|
|
599
|
+
*/
|
|
600
|
+
declare class UilmTranslateService {
|
|
601
|
+
private readonly store;
|
|
602
|
+
/** Active language as a signal. */
|
|
603
|
+
readonly activeLang: Signal<string>;
|
|
604
|
+
/**
|
|
605
|
+
* Signal-based translation. Auto-updates on language change
|
|
606
|
+
* and when new translations are loaded.
|
|
607
|
+
*/
|
|
608
|
+
t(key: string, params?: Record<string, unknown>): Signal<string>;
|
|
609
|
+
/** Synchronous translation snapshot. Does NOT react to changes. */
|
|
610
|
+
translate(key: string, params?: Record<string, unknown>): string;
|
|
611
|
+
/** Current active language code. */
|
|
612
|
+
getActiveLang(): string;
|
|
613
|
+
/** Set active language. */
|
|
614
|
+
setActiveLang(lang: string): void;
|
|
615
|
+
/**
|
|
616
|
+
* Signal-based batch translation. Reactive to lang and translation changes.
|
|
617
|
+
*/
|
|
618
|
+
tMany(keys: string[], params?: Record<string, unknown>): Signal<Record<string, string>>;
|
|
619
|
+
/** Synchronous batch translation snapshot. */
|
|
620
|
+
translateMany(keys: string[], params?: Record<string, unknown>): Record<string, string>;
|
|
621
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UilmTranslateService, never>;
|
|
622
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<UilmTranslateService>;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
declare class UilmLoadingScreenComponent {
|
|
626
|
+
readonly title: i0.InputSignal<string>;
|
|
627
|
+
readonly description: i0.InputSignal<string>;
|
|
628
|
+
/**
|
|
629
|
+
* Optional custom template to replace the entire default loading UI.
|
|
630
|
+
*
|
|
631
|
+
* @example
|
|
632
|
+
* ```html
|
|
633
|
+
* <ng-template #customLoading>
|
|
634
|
+
* <div class="my-loading">
|
|
635
|
+
* <img src="assets/logo.svg" />
|
|
636
|
+
* <p>Please wait...</p>
|
|
637
|
+
* </div>
|
|
638
|
+
* </ng-template>
|
|
639
|
+
*
|
|
640
|
+
* <uilm-loading-screen [customTemplate]="customLoading" />
|
|
641
|
+
* ```
|
|
642
|
+
*/
|
|
643
|
+
readonly customTemplate: i0.InputSignal<TemplateRef<unknown> | undefined>;
|
|
644
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<UilmLoadingScreenComponent, never>;
|
|
645
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<UilmLoadingScreenComponent, "uilm-loading-screen", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "customTemplate": { "alias": "customTemplate"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Flattens a nested object into dot-notation keys.
|
|
650
|
+
*
|
|
651
|
+
* @example
|
|
652
|
+
* ```typescript
|
|
653
|
+
* flattenJson({ LABEL: { HELLO: 'Hello', WORLD: 'World' }, BTN: { SAVE: 'Save' } })
|
|
654
|
+
* // → { 'LABEL.HELLO': 'Hello', 'LABEL.WORLD': 'World', 'BTN.SAVE': 'Save' }
|
|
655
|
+
* ```
|
|
656
|
+
*/
|
|
657
|
+
declare function flattenJson(obj: Record<string, unknown>, parentKey?: string, separator?: string, _visited?: Set<object>): Record<string, string>;
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Creates an empty record with keys for each provided language.
|
|
661
|
+
* Useful for initializing multilingual form models.
|
|
662
|
+
*
|
|
663
|
+
* @example
|
|
664
|
+
* createI18nRecord(['en', 'de', 'fr']) // { en: '', de: '', fr: '' }
|
|
665
|
+
*/
|
|
666
|
+
declare function createI18nRecord(langs: string[]): Record<string, string>;
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Convert a short language code to a full locale code using the provided mapping.
|
|
670
|
+
* Returns the original code if no mapping is found or if it's already a full code.
|
|
671
|
+
*/
|
|
672
|
+
declare function toFullLangCode(lang: string, mapping: Record<string, string>): string;
|
|
673
|
+
/**
|
|
674
|
+
* Convert a full locale code (e.g. 'en-US') to a short code (e.g. 'en').
|
|
675
|
+
*/
|
|
676
|
+
declare function toShortLangCode(fullCode: string): string;
|
|
677
|
+
/**
|
|
678
|
+
* Build a reverse mapping from full locale codes to short codes.
|
|
679
|
+
*/
|
|
680
|
+
declare function buildReverseMapping(localeMapping: Record<string, string>): Record<string, string>;
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Provides a test-friendly translation setup with in-memory translations.
|
|
684
|
+
* No HTTP calls are made.
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* ```typescript
|
|
688
|
+
* TestBed.configureTestingModule({
|
|
689
|
+
* providers: [
|
|
690
|
+
* provideBlocksLocalizationTesting({
|
|
691
|
+
* en: { 'dashboard.LABEL.HELLO': 'Hello', 'dashboard.LABEL.WORLD': 'World' },
|
|
692
|
+
* de: { 'dashboard.LABEL.HELLO': 'Hallo', 'dashboard.LABEL.WORLD': 'Welt' },
|
|
693
|
+
* }),
|
|
694
|
+
* ],
|
|
695
|
+
* });
|
|
696
|
+
* ```
|
|
697
|
+
*/
|
|
698
|
+
declare function provideBlocksLocalizationTesting(translations?: Record<string, Record<string, string>>, config?: Partial<BlocksLocalizationConfig>): i0.EnvironmentProviders;
|
|
699
|
+
|
|
700
|
+
export { BLOCKS_LOCALIZATION_CONFIG, BlocksLangSwitcher, MultiLangPipe, UilmIndexedDbCache, UilmLoader, UilmLoadingScreenComponent, UilmStore, UilmTranslateDirective, UilmTranslatePipe, UilmTranslateService, buildReverseMapping, createI18nRecord, flattenJson, provideBlocksLocalization, provideBlocksLocalizationTesting, provideUilmScope, toFullLangCode, toShortLangCode };
|
|
701
|
+
export type { BlocksLocalizationConfig, TranslationMap, UilmCacheStorage, UilmLangStorage, UilmLanguage, UilmLoadingStrategy, UilmModule, UilmModuleEntry, UilmScopeConfig };
|