@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.
@@ -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 };