mn-angular-lib 0.0.53 → 0.0.54
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.
|
@@ -606,6 +606,7 @@ class MnLanguageService {
|
|
|
606
606
|
_translations = {};
|
|
607
607
|
_locale$ = new BehaviorSubject('en');
|
|
608
608
|
_urlPattern = null;
|
|
609
|
+
_debug = false;
|
|
609
610
|
/** Observable of the current active locale. */
|
|
610
611
|
locale$ = this._locale$.asObservable();
|
|
611
612
|
constructor(http) {
|
|
@@ -615,11 +616,23 @@ class MnLanguageService {
|
|
|
615
616
|
get locale() {
|
|
616
617
|
return this._locale$.value;
|
|
617
618
|
}
|
|
619
|
+
/**
|
|
620
|
+
* Enable or disable debug logging.
|
|
621
|
+
*/
|
|
622
|
+
setDebug(enabled) {
|
|
623
|
+
this._debug = enabled;
|
|
624
|
+
if (enabled) {
|
|
625
|
+
console.log(`[MnLanguage] Debug mode enabled`);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
618
628
|
/**
|
|
619
629
|
* Configure the URL pattern used to fetch translation files.
|
|
620
630
|
* Use `{locale}` as placeholder, e.g. `"assets/i18n/{locale}.json"`.
|
|
621
631
|
*/
|
|
622
632
|
configure(urlPattern) {
|
|
633
|
+
if (this._debug) {
|
|
634
|
+
console.log(`[MnLanguage] Configured urlPattern: ${urlPattern}`);
|
|
635
|
+
}
|
|
623
636
|
this._urlPattern = urlPattern;
|
|
624
637
|
}
|
|
625
638
|
/**
|
|
@@ -634,9 +647,15 @@ class MnLanguageService {
|
|
|
634
647
|
return;
|
|
635
648
|
}
|
|
636
649
|
const url = this._urlPattern.replace('{locale}', locale);
|
|
650
|
+
if (this._debug) {
|
|
651
|
+
console.log(`[MnLanguage] Loading locale "${locale}" from ${url}`);
|
|
652
|
+
}
|
|
637
653
|
try {
|
|
638
654
|
const map = await firstValueFrom(this.http.get(url));
|
|
639
655
|
this._translations[locale] = map ?? {};
|
|
656
|
+
if (this._debug) {
|
|
657
|
+
console.log(`[MnLanguage] Loaded locale "${locale}"`, this._translations[locale]);
|
|
658
|
+
}
|
|
640
659
|
}
|
|
641
660
|
catch (err) {
|
|
642
661
|
console.warn(`[MnLanguage] Failed to load translations from ${url}`, err);
|
|
@@ -647,6 +666,9 @@ class MnLanguageService {
|
|
|
647
666
|
* Switch the active locale. Loads translations if not yet loaded.
|
|
648
667
|
*/
|
|
649
668
|
async setLocale(locale) {
|
|
669
|
+
if (this._debug) {
|
|
670
|
+
console.log(`[MnLanguage] Setting locale to "${locale}"`);
|
|
671
|
+
}
|
|
650
672
|
await this.loadLocale(locale);
|
|
651
673
|
this._locale$.next(locale);
|
|
652
674
|
}
|
|
@@ -667,8 +689,11 @@ class MnLanguageService {
|
|
|
667
689
|
*/
|
|
668
690
|
translate(key, params) {
|
|
669
691
|
const map = this._translations[this.locale] ?? {};
|
|
670
|
-
let value = map
|
|
692
|
+
let value = this.getValueFromMap(map, key);
|
|
671
693
|
if (value === undefined) {
|
|
694
|
+
if (this._debug) {
|
|
695
|
+
console.warn(`[MnLanguage] Missing translation for key: "${key}" in locale: "${this.locale}"`);
|
|
696
|
+
}
|
|
672
697
|
return key;
|
|
673
698
|
}
|
|
674
699
|
if (params) {
|
|
@@ -678,6 +703,21 @@ class MnLanguageService {
|
|
|
678
703
|
}
|
|
679
704
|
return value;
|
|
680
705
|
}
|
|
706
|
+
/**
|
|
707
|
+
* Helper to retrieve a value from a potentially nested translation map using a dot-notated key.
|
|
708
|
+
*/
|
|
709
|
+
getValueFromMap(map, key) {
|
|
710
|
+
if (map[key] !== undefined)
|
|
711
|
+
return map[key];
|
|
712
|
+
const parts = key.split('.');
|
|
713
|
+
let current = map;
|
|
714
|
+
for (const part of parts) {
|
|
715
|
+
if (current === null || typeof current !== 'object')
|
|
716
|
+
return undefined;
|
|
717
|
+
current = current[part];
|
|
718
|
+
}
|
|
719
|
+
return typeof current === 'string' ? current : undefined;
|
|
720
|
+
}
|
|
681
721
|
/**
|
|
682
722
|
* Shorthand alias for `translate`.
|
|
683
723
|
*/
|
|
@@ -739,6 +779,7 @@ class MnConfigService {
|
|
|
739
779
|
*/
|
|
740
780
|
async load(url, debugMode = false) {
|
|
741
781
|
this._debugMode = debugMode;
|
|
782
|
+
this.lang.setDebug(debugMode);
|
|
742
783
|
let text;
|
|
743
784
|
try {
|
|
744
785
|
text = await firstValueFrom(this.http.get(url, { responseType: 'text' }));
|
|
@@ -768,9 +809,12 @@ class MnConfigService {
|
|
|
768
809
|
const langCfg = cfg.language;
|
|
769
810
|
if (isPlainObject(langCfg) && typeof langCfg['urlPattern'] === 'string') {
|
|
770
811
|
const lc = langCfg;
|
|
812
|
+
if (this._debugMode) {
|
|
813
|
+
console.log(`[MnConfig] Applying language config from file`, lc);
|
|
814
|
+
}
|
|
771
815
|
this.lang.configure(lc.urlPattern);
|
|
772
816
|
const effectiveLocale = this.lang.resolveLocaleForDomain(lc.domainLocaleMap, lc.defaultLocale);
|
|
773
|
-
const localesToLoad = lc.preload ?? [effectiveLocale];
|
|
817
|
+
const localesToLoad = Array.from(new Set([...(lc.preload ?? []), effectiveLocale]));
|
|
774
818
|
await Promise.all(localesToLoad.map(l => this.lang.loadLocale(l)));
|
|
775
819
|
await this.lang.setLocale(effectiveLocale);
|
|
776
820
|
}
|
|
@@ -791,9 +835,12 @@ class MnConfigService {
|
|
|
791
835
|
const langCfg = config['language'];
|
|
792
836
|
if (isPlainObject(langCfg) && typeof langCfg['urlPattern'] === 'string') {
|
|
793
837
|
const lc = langCfg;
|
|
838
|
+
if (this._debugMode) {
|
|
839
|
+
console.log(`[MnConfig] Applying language config from object`, lc);
|
|
840
|
+
}
|
|
794
841
|
this.lang.configure(lc.urlPattern);
|
|
795
842
|
const effectiveLocale = this.lang.resolveLocaleForDomain(lc.domainLocaleMap, lc.defaultLocale);
|
|
796
|
-
const localesToLoad = lc.preload ?? [effectiveLocale];
|
|
843
|
+
const localesToLoad = Array.from(new Set([...(lc.preload ?? []), effectiveLocale]));
|
|
797
844
|
await Promise.all(localesToLoad.map(l => this.lang.loadLocale(l)));
|
|
798
845
|
await this.lang.setLocale(effectiveLocale);
|
|
799
846
|
}
|
|
@@ -1278,7 +1325,7 @@ function provideMnComponentConfig(token, componentName, initial) {
|
|
|
1278
1325
|
const cfg = resolveConfig();
|
|
1279
1326
|
// Re-resolve translatable values whenever the locale changes.
|
|
1280
1327
|
// skip(1) because the current locale was already used for the initial resolve.
|
|
1281
|
-
const sub = lang.locale$.
|
|
1328
|
+
const sub = lang.locale$.subscribe(() => {
|
|
1282
1329
|
const updated = resolveConfig();
|
|
1283
1330
|
// Mutate the existing object in place so all template bindings pick up the new values.
|
|
1284
1331
|
for (const key of Object.keys(updated)) {
|
|
@@ -6578,6 +6625,9 @@ function provideMnLanguage(config) {
|
|
|
6578
6625
|
provide: APP_INITIALIZER,
|
|
6579
6626
|
multi: true,
|
|
6580
6627
|
useFactory: (svc) => async () => {
|
|
6628
|
+
if (config.debug) {
|
|
6629
|
+
svc.setDebug(true);
|
|
6630
|
+
}
|
|
6581
6631
|
svc.configure(config.urlPattern);
|
|
6582
6632
|
const effectiveLocale = svc.resolveLocaleForDomain(config.domainLocaleMap, config.defaultLocale);
|
|
6583
6633
|
const localesToLoad = config.preload ?? [effectiveLocale];
|