diff --git a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts index 6c10ed6dc1..71fa405b04 100644 --- a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts @@ -1,7 +1,8 @@ import { Injectable } from '@angular/core'; -import { Observable, Subject } from 'rxjs'; -import { map, switchMap, take } from 'rxjs/operators'; +import { Observable, Subject,of } from 'rxjs'; +import { map, switchMap, take, } from 'rxjs/operators'; import { AbpApplicationConfigurationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-configuration.service'; +import { AbpApplicationLocalizationService } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/abp-application-localization.service'; import { ApplicationConfigurationDto, ApplicationGlobalFeatureConfigurationDto, @@ -14,21 +15,45 @@ import { InternalStore } from '../utils/internal-store-utils'; export class ConfigStateService { private readonly store = new InternalStore({} as ApplicationConfigurationDto); private includeLocalizationResources = false; - + get createOnUpdateStream() { return this.store.sliceUpdate; } private updateSubject = new Subject(); - constructor(private abpConfigService: AbpApplicationConfigurationService) { + constructor( + private abpConfigService: AbpApplicationConfigurationService, + private abpApplicationLocalizationService: AbpApplicationLocalizationService, + ) { this.initUpdateStream(); } private initUpdateStream() { this.updateSubject - .pipe(switchMap(() => this.abpConfigService.get({ includeLocalizationResources:this.includeLocalizationResources}))) - .subscribe(res => this.store.set(res)); + .pipe( + switchMap(() => + this.abpConfigService.get({ + includeLocalizationResources: this.includeLocalizationResources, + }), + ), + ) + .pipe(switchMap(appState => this.getLocalizationAndCombineWithAppState(appState))) + .subscribe(res => { + return this.store.set(res); + }); + } + + private getLocalizationAndCombineWithAppState( + appState: ApplicationConfigurationDto, + ): Observable { + return this.abpApplicationLocalizationService + .get({ cultureName: appState.localization.currentCulture.name, onlyDynamics: false }) + .pipe( + switchMap(result => + of({ ...appState, localization: { ...appState.localization, ...result } }), + ), + ); } refreshAppState() { diff --git a/npm/ng-packs/packages/core/src/lib/services/localization.service.ts b/npm/ng-packs/packages/core/src/lib/services/localization.service.ts index f41c5c9426..15ac76dfec 100644 --- a/npm/ng-packs/packages/core/src/lib/services/localization.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/localization.service.ts @@ -4,7 +4,10 @@ import { BehaviorSubject, combineLatest, from, Observable, Subject } from 'rxjs' import { filter, map, mapTo, switchMap } from 'rxjs/operators'; import { ABP } from '../models/common'; import { LocalizationWithDefault } from '../models/localization'; -import { ApplicationConfigurationDto } from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models'; +import { + ApplicationConfigurationDto, + ApplicationLocalizationResourceDto, +} from '../proxy/volo/abp/asp-net-core/mvc/application-configurations/models'; import { localizations$ } from '../tokens/localization.token'; import { CORE_OPTIONS } from '../tokens/options.token'; import { createLocalizer, createLocalizerWithFallback } from '../utils/localization-utils'; @@ -55,21 +58,32 @@ export class LocalizationService { this.initLocalizationValues(); } + private initLocalizationValues() { localizations$.subscribe(val => this.addLocalization(val)); - const remoteLocalizations$ = this.configState.getDeep$('localization.values') as Observable< + const legacyResources$ = this.configState.getDeep$('localization.values') as Observable< Record> >; + + const remoteLocalizations$ = this.configState.getDeep$('localization.resources') as Observable< + Record + >; + const currentLanguage$ = this.sessionState.getLanguage$(); const uiLocalizations$ = combineLatest([currentLanguage$, this.uiLocalizations$]).pipe( map(([currentLang, localizations]) => localizations.get(currentLang)), ); - combineLatest([remoteLocalizations$, uiLocalizations$]) + combineLatest([legacyResources$, remoteLocalizations$, uiLocalizations$]) .pipe( - map(([remote, local]) => { + map(([legacy, resource, local]) => { + + if(!resource){ + return; + } + const remote = combineLegacyandNewResources(legacy || {}, resource); if (remote) { if (!local) { local = new Map(); @@ -250,3 +264,43 @@ export class LocalizationService { return localization || defaultValue || (key as string); } } + + +function recursivelyMergeBaseResources (baseResourceName: string, source: ResourceDto) { + const item = source[baseResourceName]; + + if (item.baseResources.length === 0) { + return item; + } + + return item.baseResources.reduce((acc,baseResource) => { + const baseItem = recursivelyMergeBaseResources(baseResource, source); + const texts = { ...baseItem.texts, ...item.texts }; + return {...acc,texts} + },item); + +}; + +function mergeResourcesWithBaseResource(resource: ResourceDto):ResourceDto { + const entities = Object.keys(resource).map((key) => { + const newValue = recursivelyMergeBaseResources(key,resource) + return [key,newValue] + }); + return entities.reduce((acc,[key,value]) => ({...acc,[key]:value}),{}) +} + + + +function combineLegacyandNewResources( + legacy: LegacyLanguageDto, + resource: ResourceDto, +): LegacyLanguageDto { + const mergedResource = mergeResourcesWithBaseResource(resource); + + return Object.entries(mergedResource).reduce((acc, [key, value]) => { + return { ...acc, [key]: value.texts }; + }, legacy); +} + +type LegacyLanguageDto = Record>; +type ResourceDto = Record;