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 5fea751b14..8708eecfdb 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 @@ -7,7 +7,7 @@ import { SetLanguage } from '../actions/session.actions'; import { Config } from '../models/config'; import { ConfigState } from '../states/config.state'; import { registerLocale } from '../utils/initial-utils'; -import { localize, localizeWithFallback } from '../utils/localization-utils'; +import { createLocalizer, createLocalizerWithFallback } from '../utils/localization-utils'; type ShouldReuseRoute = (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) => boolean; @@ -79,17 +79,15 @@ export class LocalizationService { } localize(resourceName: string, key: string, defaultValue: string): Observable { - return this.store - .select(ConfigState.getOne('localization')) - .pipe(map(localize(resourceName, key, defaultValue))); + return this.store.select(ConfigState.getOne('localization')).pipe( + map(createLocalizer), + map(localize => localize(resourceName, key, defaultValue)), + ); } localizeSync(resourceName: string, key: string, defaultValue: string): string { - return localize( - resourceName, - key, - defaultValue, - )(this.store.selectSnapshot(ConfigState.getOne('localization'))); + const localization = this.store.selectSnapshot(ConfigState.getOne('localization')); + return createLocalizer(localization)(resourceName, key, defaultValue); } localizeWithFallback( @@ -97,16 +95,14 @@ export class LocalizationService { keys: string[], defaultValue: string, ): Observable { - return this.store - .select(ConfigState.getOne('localization')) - .pipe(map(localizeWithFallback(resourceNames, keys, defaultValue))); + return this.store.select(ConfigState.getOne('localization')).pipe( + map(createLocalizerWithFallback), + map(localizeWithFallback => localizeWithFallback(resourceNames, keys, defaultValue)), + ); } localizeWithFallbackSync(resourceNames: string[], keys: string[], defaultValue: string): string { - return localizeWithFallback( - resourceNames, - keys, - defaultValue, - )(this.store.selectSnapshot(ConfigState.getOne('localization'))); + const localization = this.store.selectSnapshot(ConfigState.getOne('localization')); + return createLocalizerWithFallback(localization)(resourceNames, keys, defaultValue); } } diff --git a/npm/ng-packs/packages/core/src/lib/tests/localization-utils.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/localization-utils.spec.ts new file mode 100644 index 0000000000..f8bead7eda --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tests/localization-utils.spec.ts @@ -0,0 +1,90 @@ +import { createLocalizer, createLocalizerWithFallback } from '../utils/localization-utils'; + +describe('Localization Utils', () => { + describe('#createLocalizer', () => { + const localize = createLocalizer({ + values: { foo: { bar: 'baz' }, x: { y: 'z' } }, + defaultResourceName: 'x', + currentCulture: null, + languages: [], + }); + + test.each` + resource | key | defaultValue | expected + ${'_'} | ${'TEST'} | ${'DEFAULT'} | ${'TEST'} + ${'foo'} | ${'bar'} | ${'DEFAULT'} | ${'baz'} + ${'x'} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} + ${'a'} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} + ${''} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} + ${undefined} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} + ${'foo'} | ${'y'} | ${'DEFAULT'} | ${'DEFAULT'} + ${'x'} | ${'y'} | ${'DEFAULT'} | ${'z'} + ${'a'} | ${'y'} | ${'DEFAULT'} | ${'DEFAULT'} + ${''} | ${'y'} | ${'DEFAULT'} | ${'DEFAULT'} + ${undefined} | ${'y'} | ${'DEFAULT'} | ${'DEFAULT'} + ${'foo'} | ${''} | ${'DEFAULT'} | ${'DEFAULT'} + ${'x'} | ${''} | ${'DEFAULT'} | ${'DEFAULT'} + ${'a'} | ${''} | ${'DEFAULT'} | ${'DEFAULT'} + ${''} | ${''} | ${'DEFAULT'} | ${'DEFAULT'} + ${undefined} | ${''} | ${'DEFAULT'} | ${'DEFAULT'} + ${'foo'} | ${undefined} | ${'DEFAULT'} | ${'DEFAULT'} + ${'x'} | ${undefined} | ${'DEFAULT'} | ${'DEFAULT'} + ${'a'} | ${undefined} | ${'DEFAULT'} | ${'DEFAULT'} + ${''} | ${undefined} | ${'DEFAULT'} | ${'DEFAULT'} + ${undefined} | ${undefined} | ${'DEFAULT'} | ${'DEFAULT'} + `( + 'should return $expected when resource name is $resource and key is $key', + ({ resource, key, defaultValue, expected }) => { + const result = localize(resource, key, defaultValue); + + expect(result).toBe(expected); + }, + ); + }); + + describe('#createLocalizerWithFallback', () => { + const localizeWithFallback = createLocalizerWithFallback({ + values: { foo: { bar: 'baz' }, x: { y: 'z' } }, + defaultResourceName: 'x', + currentCulture: null, + languages: [], + }); + + test.each` + resources | keys | defaultValue | expected + ${['', '_']} | ${['TEST', 'OTHER']} | ${'DEFAULT'} | ${'TEST'} + ${['foo']} | ${['bar']} | ${'DEFAULT'} | ${'baz'} + ${['x']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['foo']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['x']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['a', 'b', 'c']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${[]} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['foo']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'baz'} + ${['x']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['a', 'b', 'c']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${[]} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['foo']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['x']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['foo']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['x']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + `( + 'should return $expected when resource names are $resources and keys are $keys', + ({ resources, keys, defaultValue, expected }) => { + const result = localizeWithFallback(resources, keys, defaultValue); + + expect(result).toBe(expected); + }, + ); + }); +}); diff --git a/npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts index e17d53e463..9d6f6ba3bf 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/localization.service.spec.ts @@ -79,6 +79,7 @@ describe('LocalizationService', () => { describe('#localize', () => { test.each` resource | key | defaultValue | expected + ${'_'} | ${'TEST'} | ${'DEFAULT'} | ${'TEST'} ${'foo'} | ${'bar'} | ${'DEFAULT'} | ${'baz'} ${'x'} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} ${'a'} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} @@ -119,6 +120,7 @@ describe('LocalizationService', () => { describe('#localizeSync', () => { test.each` resource | key | defaultValue | expected + ${'_'} | ${'TEST'} | ${'DEFAULT'} | ${'TEST'} ${'foo'} | ${'bar'} | ${'DEFAULT'} | ${'baz'} ${'x'} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} ${'a'} | ${'bar'} | ${'DEFAULT'} | ${'DEFAULT'} @@ -156,32 +158,33 @@ describe('LocalizationService', () => { describe('#localizeWithFallback', () => { test.each` - resources | keys | defaultValue | expected - ${['foo']} | ${['bar']} | ${'DEFAULT'} | ${'baz'} - ${['x']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['a', 'b', 'c']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${[]} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['foo']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['x']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['a', 'b', 'c']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${[]} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['foo']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'baz'} - ${['x']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${['a', 'b', 'c']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${['']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${[]} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${['foo']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['x']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['a', 'b', 'c']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${[]} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['foo']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${['x']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${['a', 'b', 'c']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${['']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${[]} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + resources | keys | defaultValue | expected + ${['', '_']} | ${['TEST', 'OTHER']} | ${'DEFAULT'} | ${'TEST'} + ${['foo']} | ${['bar']} | ${'DEFAULT'} | ${'baz'} + ${['x']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['foo']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['x']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['a', 'b', 'c']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${[]} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['foo']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'baz'} + ${['x']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['a', 'b', 'c']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${[]} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['foo']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['x']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['foo']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['x']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} `( 'should return observable $expected when resource names are $resources and keys are $keys', async ({ resources, keys, defaultValue, expected }) => { @@ -203,32 +206,33 @@ describe('LocalizationService', () => { describe('#localizeWithFallbackSync', () => { test.each` - resources | keys | defaultValue | expected - ${['foo']} | ${['bar']} | ${'DEFAULT'} | ${'baz'} - ${['x']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['a', 'b', 'c']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${[]} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['foo']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['x']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['a', 'b', 'c']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['']} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${[]} | ${['y']} | ${'DEFAULT'} | ${'z'} - ${['foo']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'baz'} - ${['x']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${['a', 'b', 'c']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${['']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${[]} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} - ${['foo']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['x']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['a', 'b', 'c']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${[]} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} - ${['foo']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${['x']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${['a', 'b', 'c']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${['']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} - ${[]} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + resources | keys | defaultValue | expected + ${['', '_']} | ${['TEST', 'OTHER']} | ${'DEFAULT'} | ${'TEST'} + ${['foo']} | ${['bar']} | ${'DEFAULT'} | ${'baz'} + ${['x']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${['bar']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['foo']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['x']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['a', 'b', 'c']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['']} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${[]} | ${['y']} | ${'DEFAULT'} | ${'z'} + ${['foo']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'baz'} + ${['x']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['a', 'b', 'c']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['']} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${[]} | ${['bar', 'y']} | ${'DEFAULT'} | ${'z'} + ${['foo']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['x']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${['']} | ${'DEFAULT'} | ${'DEFAULT'} + ${['foo']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['x']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['a', 'b', 'c']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${['']} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} + ${[]} | ${[]} | ${'DEFAULT'} | ${'DEFAULT'} `( 'should return $expected when resource names are $resources and keys are $keys', ({ resources, keys, defaultValue, expected }) => { diff --git a/npm/ng-packs/packages/core/src/lib/utils/index.ts b/npm/ng-packs/packages/core/src/lib/utils/index.ts index 6f6b0585d9..4dde8134ef 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/index.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/index.ts @@ -3,6 +3,7 @@ export * from './form-utils'; export * from './generator-utils'; export * from './initial-utils'; export * from './lazy-load-utils'; +export * from './localization-utils'; export * from './number-utils'; export * from './route-utils'; export * from './rxjs-utils'; diff --git a/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts b/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts index 2a14b8d014..31a73b818d 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/localization-utils.ts @@ -1,8 +1,8 @@ import { ApplicationConfiguration } from '../models/application-configuration'; -export function localize(resourceName: string, key: string, defaultValue: string) { +export function createLocalizer(localization: ApplicationConfiguration.Localization) { /* tslint:disable-next-line:only-arrow-functions */ - return function(localization: ApplicationConfiguration.Localization) { + return function(resourceName: string, key: string, defaultValue: string) { if (resourceName === '_') return key; const resource = localization.values[resourceName]; @@ -13,13 +13,20 @@ export function localize(resourceName: string, key: string, defaultValue: string }; } -export function localizeWithFallback( - resourceNames: string[], - keys: string[], - defaultValue: string, -) { +export function createLocalizerWithFallback(localization: ApplicationConfiguration.Localization) { + const findLocalization = createLocalizationFinder(localization); /* tslint:disable-next-line:only-arrow-functions */ - return function(localization: ApplicationConfiguration.Localization) { + return function(resourceNames: string[], keys: string[], defaultValue: string) { + const { localized } = findLocalization(resourceNames, keys); + return localized || defaultValue; + }; +} + +function createLocalizationFinder(localization: ApplicationConfiguration.Localization) { + const localize = createLocalizer(localization); + + /* tslint:disable-next-line:only-arrow-functions */ + return function(resourceNames: string[], keys: string[]) { resourceNames = resourceNames.concat(localization.defaultResourceName).filter(Boolean); const resourceCount = resourceNames.length; @@ -29,11 +36,12 @@ export function localizeWithFallback( const resourceName = resourceNames[i]; for (let j = 0; j < keyCount; j++) { - const localized = localize(resourceName, keys[j], null)(localization); - if (localized) return localized; + const key = keys[j]; + const localized = localize(resourceName, key, null); + if (localized) return { resourceName, key, localized }; } } - return defaultValue; + return { resourceName: undefined, key: undefined, localized: undefined }; }; }