@jsverse/transloco 7.5.1 → 7.6.0

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, Injectable, Injector, Inject, Optional, Component, Input, TemplateRef, DestroyRef, ChangeDetectorRef, ElementRef, ViewContainerRef, Renderer2, Directive, Pipe, NgModule, makeEnvironmentProviders, APP_INITIALIZER } from '@angular/core';
2
+ import { InjectionToken, inject, Injectable, Injector, Inject, DestroyRef, Optional, Component, Input, TemplateRef, ChangeDetectorRef, ElementRef, ViewContainerRef, Renderer2, Directive, Pipe, NgModule, makeEnvironmentProviders, APP_INITIALIZER, assertInInjectionContext, runInInjectionContext, isSignal, computed } from '@angular/core';
3
3
  import { of, take, from, map, Subject, BehaviorSubject, forkJoin, retry, tap, catchError, shareReplay, switchMap, combineLatest, EMPTY } from 'rxjs';
4
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
5
5
 
6
6
  class DefaultLoader {
7
7
  translations;
@@ -12,7 +12,7 @@ class DefaultLoader {
12
12
  return of(this.translations.get(lang) || {});
13
13
  }
14
14
  }
15
- const TRANSLOCO_LOADER = new InjectionToken('TRANSLOCO_LOADER');
15
+ const TRANSLOCO_LOADER = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'TRANSLOCO_LOADER' : '');
16
16
 
17
17
  function getValue(obj, path) {
18
18
  if (!obj) {
@@ -143,7 +143,7 @@ function unflatten(obj) {
143
143
  return result;
144
144
  }
145
145
 
146
- const TRANSLOCO_CONFIG = new InjectionToken('TRANSLOCO_CONFIG', {
146
+ const TRANSLOCO_CONFIG = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'TRANSLOCO_CONFIG' : '', {
147
147
  providedIn: 'root',
148
148
  factory: () => defaultConfig,
149
149
  });
@@ -186,7 +186,7 @@ function translocoConfig(config = {}) {
186
186
  };
187
187
  }
188
188
 
189
- const TRANSLOCO_TRANSPILER = new InjectionToken('TRANSLOCO_TRANSPILER');
189
+ const TRANSLOCO_TRANSPILER = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'TRANSLOCO_TRANSPILER' : '');
190
190
  class DefaultTranspiler {
191
191
  config = inject(TRANSLOCO_CONFIG, { optional: true }) ?? defaultConfig;
192
192
  get interpolationMatcher() {
@@ -330,7 +330,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
330
330
  type: Injectable
331
331
  }] });
332
332
 
333
- const TRANSLOCO_MISSING_HANDLER = new InjectionToken('TRANSLOCO_MISSING_HANDLER');
333
+ const TRANSLOCO_MISSING_HANDLER = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode
334
+ ? 'TRANSLOCO_MISSING_HANDLER'
335
+ : '');
334
336
  class DefaultMissingHandler {
335
337
  handle(key, config) {
336
338
  if (config.missingHandler.logMissingKey && !config.prodMode) {
@@ -346,7 +348,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
346
348
  type: Injectable
347
349
  }] });
348
350
 
349
- const TRANSLOCO_INTERCEPTOR = new InjectionToken('TRANSLOCO_INTERCEPTOR');
351
+ const TRANSLOCO_INTERCEPTOR = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'TRANSLOCO_INTERCEPTOR' : '');
350
352
  class DefaultInterceptor {
351
353
  preSaveTranslation(translation) {
352
354
  return translation;
@@ -361,7 +363,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
361
363
  type: Injectable
362
364
  }] });
363
365
 
364
- const TRANSLOCO_FALLBACK_STRATEGY = new InjectionToken('TRANSLOCO_FALLBACK_STRATEGY');
366
+ const TRANSLOCO_FALLBACK_STRATEGY = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode
367
+ ? 'TRANSLOCO_FALLBACK_STRATEGY'
368
+ : '');
365
369
  class DefaultFallbackStrategy {
366
370
  userConfig;
367
371
  constructor(userConfig) {
@@ -503,6 +507,7 @@ class TranslocoService {
503
507
  events = new Subject();
504
508
  events$ = this.events.asObservable();
505
509
  config;
510
+ destroyRef = inject(DestroyRef);
506
511
  constructor(loader, parser, missingHandler, interceptor, userConfig, fallbackStrategy) {
507
512
  this.loader = loader;
508
513
  this.parser = parser;
@@ -524,11 +529,21 @@ class TranslocoService {
524
529
  /**
525
530
  * When we have a failure, we want to define the next language that succeeded as the active
526
531
  */
527
- this.events$.pipe(takeUntilDestroyed()).subscribe((e) => {
532
+ this.events$.subscribe((e) => {
528
533
  if (e.type === 'translationLoadSuccess' && e.wasFailure) {
529
534
  this.setActiveLang(e.payload.langName);
530
535
  }
531
536
  });
537
+ this.destroyRef.onDestroy(() => {
538
+ // Complete subjects to release observers if users forget to unsubscribe manually.
539
+ // This is important in server-side rendering.
540
+ this.lang.complete();
541
+ this.events.complete();
542
+ // As a root provider, this service is destroyed with when the application is destroyed.
543
+ // Cached values retain `this`, causing circular references that block garbage collection,
544
+ // leading to memory leaks during server-side rendering.
545
+ this.cache.clear();
546
+ });
532
547
  }
533
548
  getDefaultLang() {
534
549
  return this.defaultLang;
@@ -610,7 +625,7 @@ class TranslocoService {
610
625
  console.error(`Error while trying to load "${path}"`, error);
611
626
  }
612
627
  return this.handleFailure(path, options);
613
- }), shareReplay(1));
628
+ }), shareReplay(1), takeUntilDestroyed(this.destroyRef));
614
629
  this.cache.set(path, load$);
615
630
  return load$;
616
631
  }
@@ -892,13 +907,6 @@ class TranslocoService {
892
907
  }
893
908
  this.config.scopeMapping[scope] = alias;
894
909
  }
895
- ngOnDestroy() {
896
- // Caretaker note: since this is the root provider, it'll be destroyed when the `NgModuleRef.destroy()` is run.
897
- // Cached values capture `this`, thus leading to a circular reference and preventing the `TranslocoService` from
898
- // being GC'd. This would lead to a memory leak when server-side rendering is used since the service is created
899
- // and destroyed per each HTTP request, but any service is not getting GC'd.
900
- this.cache.clear();
901
- }
902
910
  isLoadedTranslation(lang) {
903
911
  return size(this.getTranslation(lang));
904
912
  }
@@ -1085,11 +1093,13 @@ class TemplateHandler {
1085
1093
  }
1086
1094
  }
1087
1095
 
1088
- const TRANSLOCO_LANG = new InjectionToken('TRANSLOCO_LANG');
1096
+ const TRANSLOCO_LANG = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'TRANSLOCO_LANG' : '');
1089
1097
 
1090
- const TRANSLOCO_LOADING_TEMPLATE = new InjectionToken('TRANSLOCO_LOADING_TEMPLATE');
1098
+ const TRANSLOCO_LOADING_TEMPLATE = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode
1099
+ ? 'TRANSLOCO_LOADING_TEMPLATE'
1100
+ : '');
1091
1101
 
1092
- const TRANSLOCO_SCOPE = new InjectionToken('TRANSLOCO_SCOPE');
1102
+ const TRANSLOCO_SCOPE = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'TRANSLOCO_SCOPE' : '');
1093
1103
 
1094
1104
  class LangResolver {
1095
1105
  initialized = false;
@@ -1604,9 +1614,103 @@ function getBrowserCultureLang() {
1604
1614
  return navigator.languages?.[0] ?? navigator.language;
1605
1615
  }
1606
1616
 
1617
+ /**
1618
+ * Gets the translated value of a key as Signal
1619
+ *
1620
+ * @example
1621
+ * text = translateSignal('hello');
1622
+ * textList = translateSignal(['green', 'blue']);
1623
+ * textVar = translateSignal('hello', { variable: 'world' });
1624
+ * textSpanish = translateSignal('hello', { variable: 'world' }, 'es');
1625
+ * textTodosScope = translateSignal('hello', { variable: 'world' }, { scope: 'todos' });
1626
+ *
1627
+ * @example
1628
+ * dynamicKey = signal('hello');
1629
+ * dynamicParam = signal({ variable: 'world' });
1630
+ * text = translateSignal(this.dynamicKey, this.dynamicParam);
1631
+ *
1632
+ */
1633
+ function translateSignal(key, params, lang, injector) {
1634
+ if (!injector) {
1635
+ assertInInjectionContext(translateSignal);
1636
+ }
1637
+ injector ??= inject(Injector);
1638
+ const result = runInInjectionContext(injector, () => {
1639
+ const service = inject(TranslocoService);
1640
+ const scope = resolveScope(lang);
1641
+ return toObservable(computerKeysAndParams(key, params)).pipe(switchMap((dynamic) => service.selectTranslate(dynamic.key, dynamic.params, scope)));
1642
+ });
1643
+ return toSignal(result, { initialValue: Array.isArray(key) ? [''] : '' });
1644
+ }
1645
+ /**
1646
+ * Gets the translated object of a key as Signal
1647
+ *
1648
+ * @example
1649
+ * object = translateObjectSignal('nested.object');
1650
+ * title = object().title;
1651
+ *
1652
+ * @example
1653
+ * dynamicKey = signal('nested.object');
1654
+ * dynamicParam = signal({ variable: 'world' });
1655
+ * object = translateObjectSignal(this.dynamicKey, this.dynamicParam);
1656
+ */
1657
+ function translateObjectSignal(key, params, lang, injector) {
1658
+ if (!injector) {
1659
+ assertInInjectionContext(translateObjectSignal);
1660
+ }
1661
+ injector ??= inject(Injector);
1662
+ const result = runInInjectionContext(injector, () => {
1663
+ const service = inject(TranslocoService);
1664
+ const scope = resolveScope(lang);
1665
+ return toObservable(computerKeysAndParams(key, params)).pipe(switchMap((dynamic) => service.selectTranslateObject(dynamic.key, dynamic.params, scope)));
1666
+ });
1667
+ return toSignal(result, { initialValue: Array.isArray(key) ? [] : {} });
1668
+ }
1669
+ function computerParams(params) {
1670
+ if (isSignal(params)) {
1671
+ return computed(() => params());
1672
+ }
1673
+ return computed(() => {
1674
+ return Object.entries(params).reduce((acc, [key, value]) => {
1675
+ acc[key] = isSignal(value) ? value() : value;
1676
+ return acc;
1677
+ }, {});
1678
+ });
1679
+ }
1680
+ function computerKeys(keys) {
1681
+ if (Array.isArray(keys)) {
1682
+ return computed(() => keys.map((key) => (isSignal(key) ? key() : key)));
1683
+ }
1684
+ return computed(() => keys());
1685
+ }
1686
+ function isSignalKey(key) {
1687
+ return Array.isArray(key) ? key.some(isSignal) : isSignal(key);
1688
+ }
1689
+ function isSignalParams(params) {
1690
+ return params
1691
+ ? isSignal(params) || Object.values(params).some(isSignal)
1692
+ : false;
1693
+ }
1694
+ function computerKeysAndParams(key, params) {
1695
+ const computedKeys = isSignalKey(key)
1696
+ ? computerKeys(key)
1697
+ : computed(() => key);
1698
+ const computedParams = isSignalParams(params)
1699
+ ? computerParams(params)
1700
+ : computed(() => params);
1701
+ return computed(() => ({ key: computedKeys(), params: computedParams() }));
1702
+ }
1703
+ function resolveScope(scope) {
1704
+ if (typeof scope === 'undefined' || scope === '') {
1705
+ const translocoScope = inject(TRANSLOCO_SCOPE, { optional: true });
1706
+ return translocoScope ?? undefined;
1707
+ }
1708
+ return scope;
1709
+ }
1710
+
1607
1711
  /**
1608
1712
  * Generated bundle index. Do not edit.
1609
1713
  */
1610
1714
 
1611
- export { DefaultFallbackStrategy, DefaultInterceptor, DefaultMissingHandler, DefaultTranspiler, FunctionalTranspiler, TRANSLOCO_CONFIG, TRANSLOCO_FALLBACK_STRATEGY, TRANSLOCO_INTERCEPTOR, TRANSLOCO_LANG, TRANSLOCO_LOADER, TRANSLOCO_LOADING_TEMPLATE, TRANSLOCO_MISSING_HANDLER, TRANSLOCO_SCOPE, TRANSLOCO_TRANSPILER, TestingLoader, TranslocoDirective, TranslocoModule, TranslocoPipe, TranslocoService, TranslocoTestingModule, coerceArray, defaultConfig, flatten, getBrowserCultureLang, getBrowserLang, getFunctionArgs, getLangFromScope, getPipeValue, getScopeFromLang, getValue, hasInlineLoader, isBrowser, isDefined, isEmpty, isFunction, isNil, isNumber, isObject, isScopeObject, isString, provideTransloco, provideTranslocoConfig, provideTranslocoFallbackStrategy, provideTranslocoInterceptor, provideTranslocoLang, provideTranslocoLoader, provideTranslocoLoadingTpl, provideTranslocoMissingHandler, provideTranslocoScope, provideTranslocoTranspiler, setValue, size, toCamelCase, toNumber, translate, translateObject, translocoConfig, unflatten };
1715
+ export { DefaultFallbackStrategy, DefaultInterceptor, DefaultMissingHandler, DefaultTranspiler, FunctionalTranspiler, TRANSLOCO_CONFIG, TRANSLOCO_FALLBACK_STRATEGY, TRANSLOCO_INTERCEPTOR, TRANSLOCO_LANG, TRANSLOCO_LOADER, TRANSLOCO_LOADING_TEMPLATE, TRANSLOCO_MISSING_HANDLER, TRANSLOCO_SCOPE, TRANSLOCO_TRANSPILER, TestingLoader, TranslocoDirective, TranslocoModule, TranslocoPipe, TranslocoService, TranslocoTestingModule, coerceArray, defaultConfig, flatten, getBrowserCultureLang, getBrowserLang, getFunctionArgs, getLangFromScope, getPipeValue, getScopeFromLang, getValue, hasInlineLoader, isBrowser, isDefined, isEmpty, isFunction, isNil, isNumber, isObject, isScopeObject, isString, provideTransloco, provideTranslocoConfig, provideTranslocoFallbackStrategy, provideTranslocoInterceptor, provideTranslocoLang, provideTranslocoLoader, provideTranslocoLoadingTpl, provideTranslocoMissingHandler, provideTranslocoScope, provideTranslocoTranspiler, setValue, size, toCamelCase, toNumber, translate, translateObject, translateObjectSignal, translateSignal, translocoConfig, unflatten };
1612
1716
  //# sourceMappingURL=jsverse-transloco.mjs.map