@jsverse/transloco 7.5.1 → 7.6.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/CHANGELOG.md +34 -16
- package/README.md +29 -24
- package/esm2022/index.mjs +2 -1
- package/esm2022/lib/transloco-fallback-strategy.mjs +2 -2
- package/esm2022/lib/transloco-lang.mjs +2 -2
- package/esm2022/lib/transloco-loading-template.mjs +2 -2
- package/esm2022/lib/transloco-missing-handler.mjs +3 -3
- package/esm2022/lib/transloco-scope.mjs +2 -2
- package/esm2022/lib/transloco.config.mjs +2 -2
- package/esm2022/lib/transloco.interceptor.mjs +3 -3
- package/esm2022/lib/transloco.loader.mjs +2 -2
- package/esm2022/lib/transloco.service.mjs +15 -11
- package/esm2022/lib/transloco.signal.mjs +99 -0
- package/esm2022/lib/transloco.transpiler.mjs +2 -2
- package/fesm2022/jsverse-transloco.mjs +119 -21
- package/fesm2022/jsverse-transloco.mjs.map +1 -1
- package/index.d.ts +1 -0
- package/lib/transloco.service.d.ts +2 -3
- package/lib/transloco.signal.d.ts +39 -0
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, Injectable, Injector, Inject, Optional, Component, Input, TemplateRef,
|
|
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(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(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(ngDevMode ? 'TRANSLOCO_TRANSPILER' : '');
|
|
190
190
|
class DefaultTranspiler {
|
|
191
191
|
config = inject(TRANSLOCO_CONFIG, { optional: true }) ?? defaultConfig;
|
|
192
192
|
get interpolationMatcher() {
|
|
@@ -330,7 +330,7 @@ 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(ngDevMode ? 'TRANSLOCO_MISSING_HANDLER' : '');
|
|
334
334
|
class DefaultMissingHandler {
|
|
335
335
|
handle(key, config) {
|
|
336
336
|
if (config.missingHandler.logMissingKey && !config.prodMode) {
|
|
@@ -346,7 +346,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
|
|
|
346
346
|
type: Injectable
|
|
347
347
|
}] });
|
|
348
348
|
|
|
349
|
-
const TRANSLOCO_INTERCEPTOR = new InjectionToken('TRANSLOCO_INTERCEPTOR');
|
|
349
|
+
const TRANSLOCO_INTERCEPTOR = new InjectionToken(ngDevMode ? 'TRANSLOCO_INTERCEPTOR' : '');
|
|
350
350
|
class DefaultInterceptor {
|
|
351
351
|
preSaveTranslation(translation) {
|
|
352
352
|
return translation;
|
|
@@ -361,7 +361,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImpor
|
|
|
361
361
|
type: Injectable
|
|
362
362
|
}] });
|
|
363
363
|
|
|
364
|
-
const TRANSLOCO_FALLBACK_STRATEGY = new InjectionToken('TRANSLOCO_FALLBACK_STRATEGY');
|
|
364
|
+
const TRANSLOCO_FALLBACK_STRATEGY = new InjectionToken(ngDevMode ? 'TRANSLOCO_FALLBACK_STRATEGY' : '');
|
|
365
365
|
class DefaultFallbackStrategy {
|
|
366
366
|
userConfig;
|
|
367
367
|
constructor(userConfig) {
|
|
@@ -503,6 +503,7 @@ class TranslocoService {
|
|
|
503
503
|
events = new Subject();
|
|
504
504
|
events$ = this.events.asObservable();
|
|
505
505
|
config;
|
|
506
|
+
destroyRef = inject(DestroyRef);
|
|
506
507
|
constructor(loader, parser, missingHandler, interceptor, userConfig, fallbackStrategy) {
|
|
507
508
|
this.loader = loader;
|
|
508
509
|
this.parser = parser;
|
|
@@ -524,11 +525,21 @@ class TranslocoService {
|
|
|
524
525
|
/**
|
|
525
526
|
* When we have a failure, we want to define the next language that succeeded as the active
|
|
526
527
|
*/
|
|
527
|
-
this.events$.
|
|
528
|
+
this.events$.subscribe((e) => {
|
|
528
529
|
if (e.type === 'translationLoadSuccess' && e.wasFailure) {
|
|
529
530
|
this.setActiveLang(e.payload.langName);
|
|
530
531
|
}
|
|
531
532
|
});
|
|
533
|
+
this.destroyRef.onDestroy(() => {
|
|
534
|
+
// Complete subjects to release observers if users forget to unsubscribe manually.
|
|
535
|
+
// This is important in server-side rendering.
|
|
536
|
+
this.lang.complete();
|
|
537
|
+
this.events.complete();
|
|
538
|
+
// As a root provider, this service is destroyed with when the application is destroyed.
|
|
539
|
+
// Cached values retain `this`, causing circular references that block garbage collection,
|
|
540
|
+
// leading to memory leaks during server-side rendering.
|
|
541
|
+
this.cache.clear();
|
|
542
|
+
});
|
|
532
543
|
}
|
|
533
544
|
getDefaultLang() {
|
|
534
545
|
return this.defaultLang;
|
|
@@ -610,7 +621,7 @@ class TranslocoService {
|
|
|
610
621
|
console.error(`Error while trying to load "${path}"`, error);
|
|
611
622
|
}
|
|
612
623
|
return this.handleFailure(path, options);
|
|
613
|
-
}), shareReplay(1));
|
|
624
|
+
}), shareReplay(1), takeUntilDestroyed(this.destroyRef));
|
|
614
625
|
this.cache.set(path, load$);
|
|
615
626
|
return load$;
|
|
616
627
|
}
|
|
@@ -892,13 +903,6 @@ class TranslocoService {
|
|
|
892
903
|
}
|
|
893
904
|
this.config.scopeMapping[scope] = alias;
|
|
894
905
|
}
|
|
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
906
|
isLoadedTranslation(lang) {
|
|
903
907
|
return size(this.getTranslation(lang));
|
|
904
908
|
}
|
|
@@ -1085,11 +1089,11 @@ class TemplateHandler {
|
|
|
1085
1089
|
}
|
|
1086
1090
|
}
|
|
1087
1091
|
|
|
1088
|
-
const TRANSLOCO_LANG = new InjectionToken('TRANSLOCO_LANG');
|
|
1092
|
+
const TRANSLOCO_LANG = new InjectionToken(ngDevMode ? 'TRANSLOCO_LANG' : '');
|
|
1089
1093
|
|
|
1090
|
-
const TRANSLOCO_LOADING_TEMPLATE = new InjectionToken('TRANSLOCO_LOADING_TEMPLATE');
|
|
1094
|
+
const TRANSLOCO_LOADING_TEMPLATE = new InjectionToken(ngDevMode ? 'TRANSLOCO_LOADING_TEMPLATE' : '');
|
|
1091
1095
|
|
|
1092
|
-
const TRANSLOCO_SCOPE = new InjectionToken('TRANSLOCO_SCOPE');
|
|
1096
|
+
const TRANSLOCO_SCOPE = new InjectionToken(ngDevMode ? 'TRANSLOCO_SCOPE' : '');
|
|
1093
1097
|
|
|
1094
1098
|
class LangResolver {
|
|
1095
1099
|
initialized = false;
|
|
@@ -1604,9 +1608,103 @@ function getBrowserCultureLang() {
|
|
|
1604
1608
|
return navigator.languages?.[0] ?? navigator.language;
|
|
1605
1609
|
}
|
|
1606
1610
|
|
|
1611
|
+
/**
|
|
1612
|
+
* Gets the translated value of a key as Signal
|
|
1613
|
+
*
|
|
1614
|
+
* @example
|
|
1615
|
+
* text = translateSignal('hello');
|
|
1616
|
+
* textList = translateSignal(['green', 'blue']);
|
|
1617
|
+
* textVar = translateSignal('hello', { variable: 'world' });
|
|
1618
|
+
* textSpanish = translateSignal('hello', { variable: 'world' }, 'es');
|
|
1619
|
+
* textTodosScope = translateSignal('hello', { variable: 'world' }, { scope: 'todos' });
|
|
1620
|
+
*
|
|
1621
|
+
* @example
|
|
1622
|
+
* dynamicKey = signal('hello');
|
|
1623
|
+
* dynamicParam = signal({ variable: 'world' });
|
|
1624
|
+
* text = translateSignal(this.dynamicKey, this.dynamicParam);
|
|
1625
|
+
*
|
|
1626
|
+
*/
|
|
1627
|
+
function translateSignal(key, params, lang, injector) {
|
|
1628
|
+
if (!injector) {
|
|
1629
|
+
assertInInjectionContext(translateSignal);
|
|
1630
|
+
}
|
|
1631
|
+
injector ??= inject(Injector);
|
|
1632
|
+
const result = runInInjectionContext(injector, () => {
|
|
1633
|
+
const service = inject(TranslocoService);
|
|
1634
|
+
const scope = resolveScope(lang);
|
|
1635
|
+
return toObservable(computerKeysAndParams(key, params)).pipe(switchMap((dynamic) => service.selectTranslate(dynamic.key, dynamic.params, scope)));
|
|
1636
|
+
});
|
|
1637
|
+
return toSignal(result, { initialValue: Array.isArray(key) ? [''] : '' });
|
|
1638
|
+
}
|
|
1639
|
+
/**
|
|
1640
|
+
* Gets the translated object of a key as Signal
|
|
1641
|
+
*
|
|
1642
|
+
* @example
|
|
1643
|
+
* object = translateObjectSignal('nested.object');
|
|
1644
|
+
* title = object().title;
|
|
1645
|
+
*
|
|
1646
|
+
* @example
|
|
1647
|
+
* dynamicKey = signal('nested.object');
|
|
1648
|
+
* dynamicParam = signal({ variable: 'world' });
|
|
1649
|
+
* object = translateObjectSignal(this.dynamicKey, this.dynamicParam);
|
|
1650
|
+
*/
|
|
1651
|
+
function translateObjectSignal(key, params, lang, injector) {
|
|
1652
|
+
if (!injector) {
|
|
1653
|
+
assertInInjectionContext(translateObjectSignal);
|
|
1654
|
+
}
|
|
1655
|
+
injector ??= inject(Injector);
|
|
1656
|
+
const result = runInInjectionContext(injector, () => {
|
|
1657
|
+
const service = inject(TranslocoService);
|
|
1658
|
+
const scope = resolveScope(lang);
|
|
1659
|
+
return toObservable(computerKeysAndParams(key, params)).pipe(switchMap((dynamic) => service.selectTranslateObject(dynamic.key, dynamic.params, scope)));
|
|
1660
|
+
});
|
|
1661
|
+
return toSignal(result, { initialValue: Array.isArray(key) ? [] : {} });
|
|
1662
|
+
}
|
|
1663
|
+
function computerParams(params) {
|
|
1664
|
+
if (isSignal(params)) {
|
|
1665
|
+
return computed(() => params());
|
|
1666
|
+
}
|
|
1667
|
+
return computed(() => {
|
|
1668
|
+
return Object.entries(params).reduce((acc, [key, value]) => {
|
|
1669
|
+
acc[key] = isSignal(value) ? value() : value;
|
|
1670
|
+
return acc;
|
|
1671
|
+
}, {});
|
|
1672
|
+
});
|
|
1673
|
+
}
|
|
1674
|
+
function computerKeys(keys) {
|
|
1675
|
+
if (Array.isArray(keys)) {
|
|
1676
|
+
return computed(() => keys.map((key) => (isSignal(key) ? key() : key)));
|
|
1677
|
+
}
|
|
1678
|
+
return computed(() => keys());
|
|
1679
|
+
}
|
|
1680
|
+
function isSignalKey(key) {
|
|
1681
|
+
return Array.isArray(key) ? key.some(isSignal) : isSignal(key);
|
|
1682
|
+
}
|
|
1683
|
+
function isSignalParams(params) {
|
|
1684
|
+
return params
|
|
1685
|
+
? isSignal(params) || Object.values(params).some(isSignal)
|
|
1686
|
+
: false;
|
|
1687
|
+
}
|
|
1688
|
+
function computerKeysAndParams(key, params) {
|
|
1689
|
+
const computedKeys = isSignalKey(key)
|
|
1690
|
+
? computerKeys(key)
|
|
1691
|
+
: computed(() => key);
|
|
1692
|
+
const computedParams = isSignalParams(params)
|
|
1693
|
+
? computerParams(params)
|
|
1694
|
+
: computed(() => params);
|
|
1695
|
+
return computed(() => ({ key: computedKeys(), params: computedParams() }));
|
|
1696
|
+
}
|
|
1697
|
+
function resolveScope(scope) {
|
|
1698
|
+
if (typeof scope === 'undefined' || scope === '') {
|
|
1699
|
+
const translocoScope = inject(TRANSLOCO_SCOPE, { optional: true });
|
|
1700
|
+
return translocoScope ?? undefined;
|
|
1701
|
+
}
|
|
1702
|
+
return scope;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1607
1705
|
/**
|
|
1608
1706
|
* Generated bundle index. Do not edit.
|
|
1609
1707
|
*/
|
|
1610
1708
|
|
|
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 };
|
|
1709
|
+
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
1710
|
//# sourceMappingURL=jsverse-transloco.mjs.map
|