-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* POC * e2e * Tests * tests * Update changelog * v1.0.16-rc1 * extend locale types * Tests * Update * Refactor * Update test description * Add tests * v1.0.16-rc2 * private _locale * Refactor WIP * Refactor * v1.0.16-rc3 * `defaultLocale` is protected + Component locale supports undefined * Export `Localized<>` utility type * v1.0.16-rc4 --------- Co-authored-by: Claudio Benedetti <[email protected]>
- Loading branch information
Showing
14 changed files
with
623 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"name": "@micro-lc/back-kit-engine", | ||
"version": "1.0.15", | ||
"version": "1.0.16-rc4", | ||
"description": "engine to sync react over webcomponents scaffolding + backoffice utils and types/interfaces", | ||
"license": "SEE LICENSE IN LICENSE", | ||
"author": "Mia Platform Core Team <[email protected]>", | ||
|
@@ -180,5 +180,6 @@ | |
"[email protected]": { | ||
"unplugged": true | ||
} | ||
} | ||
}, | ||
"stableVersion": "1.0.15" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import {mergeLabels, solveLocale} from '../localized-components' | ||
|
||
describe('localized-components tests - solveLocale', () => { | ||
const locale = { | ||
title: { | ||
en: 'title-en', | ||
it: 'title-it', | ||
es: 'title-es', | ||
}, | ||
subtitle: { | ||
subtitle: { | ||
en: 'subtitle-en', | ||
it: 'subtitle-it', | ||
es: 'subtitle-es', | ||
}, | ||
badge: { | ||
en: 'badge-en', | ||
it: 'badge-it', | ||
es: 'badge-es', | ||
}, | ||
} | ||
} | ||
const en = { | ||
title: 'title-en', | ||
subtitle: { | ||
subtitle: 'subtitle-en', | ||
badge: 'badge-en', | ||
} | ||
} | ||
const ita = { | ||
title: 'title-it', | ||
subtitle: { | ||
subtitle: 'subtitle-it', | ||
badge: 'badge-it', | ||
} | ||
} | ||
const es = { | ||
title: 'title-es', | ||
subtitle: { | ||
subtitle: 'subtitle-es', | ||
badge: 'badge-es', | ||
} | ||
} | ||
|
||
it.each([ | ||
[locale, 'en', en], | ||
[locale, 'it', ita], | ||
[locale, 'es', es], | ||
[locale, 'fr', en], | ||
[locale, undefined, en], | ||
])('should solve localized texts', (locale, lang, expected) => { | ||
expect(solveLocale(locale, lang)).toStrictEqual(expected) | ||
}) | ||
}) | ||
|
||
describe('localized-components tests - solveLocale edge cases', () => { | ||
it('should solve localized texts', () => { | ||
const locale = {name: {en: 'Name'}, badge: {id: 0, monthBefore: true, range: ['start', 'end'], text: {en: 'Text'}}} | ||
const expected = {name: 'Name', badge: {id: 0, monthBefore: true, range: ['start', 'end'], text: 'Text'}} | ||
|
||
// @ts-expect-error force unorthodox locale | ||
expect(solveLocale(locale)).toStrictEqual(expected) | ||
}) | ||
|
||
it('localized-components tests - solveLocale default language kicks in', () => { | ||
const {navigator} = window | ||
Object.defineProperty(window, 'navigator', {writable: true, value: {language: undefined}}) | ||
expect(solveLocale({name: {en: 'Name', it: 'Nome'}})).toStrictEqual({name: 'Name'}) | ||
Object.defineProperty(window, 'navigator', {writable: true, value: navigator}) | ||
}) | ||
}) | ||
|
||
describe('localized-components tests - mergeLables', () => { | ||
it.each([ | ||
[ | ||
{title: 'Title', subtitle: {name: 'Subtitle-new'}}, | ||
{subtitle: {name: 'Subtitle'}}, | ||
{title: 'Title', subtitle: {name: 'Subtitle-new'}} | ||
], | ||
[ | ||
{subtitle: {name: 'Subtitle-new'}}, | ||
{title: 'Title', subtitle: {name: 'Subtitle'}}, | ||
{title: 'Title', subtitle: {name: 'Subtitle-new'}} | ||
], | ||
[ | ||
{title: 'Title', subtitle: {name: 'Subtitle-new'}}, | ||
{subtitle: 'Subtitle'}, | ||
{title: 'Title', subtitle: {name: 'Subtitle-new'}} | ||
], | ||
[ | ||
{title: 'Title', subtitle: {name: 'Subtitle-new'}}, | ||
{title: 'Title', subtitle: {badge: 'Badge'}}, | ||
{title: 'Title', subtitle: {name: 'Subtitle-new', badge: 'Badge'}} | ||
], | ||
[{title: 'Title', subtitle: 'Subtitle-new'}, {subtitle: 'Subtitle'}, {title: 'Title', subtitle: 'Subtitle-new'}], | ||
[{title: 'Title'}, {subtitle: 'Subtitle'}, {title: 'Title', subtitle: 'Subtitle'}], | ||
[{}, {title: 'Title'}, {title: 'Title'}], | ||
[{title: 'Title'}, {}, {title: 'Title'}], | ||
[{title: 'Title'}, undefined, {title: 'Title'}], | ||
[undefined, {title: 'Title'}, {title: 'Title'}], | ||
[undefined, undefined, undefined], | ||
])('should merge labels', (labels, defaultLabels, expected) => { | ||
expect(mergeLabels(labels, defaultLabels)).toStrictEqual(expected) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import {type LocalizedText, DEFAULT_LANGUAGE, getLocalizedText, Localized} from '../utils/i18n' | ||
|
||
export type Labels = { | ||
[key: string]: string | undefined | Labels | ||
} | ||
|
||
export interface LocalizedComponent<L extends Labels = Labels> { | ||
customLocale?: Localized<L> | ||
locale?: L | ||
} | ||
|
||
const unique = <T>(l: T[]) => [...new Set(l)] | ||
|
||
function isValidObject (input: unknown): input is Record<string, unknown> { | ||
return Boolean(input) && typeof input === 'object' && !Array.isArray(input) | ||
} | ||
|
||
function isLocaliedText (input: unknown): input is LocalizedText { | ||
return isValidObject(input) | ||
&& Object | ||
.entries(input) | ||
.every(([key, value]) => | ||
typeof key === 'string' && key.length === 2 && typeof value === 'string') | ||
} | ||
|
||
function merge<T = unknown> (values: T, defaultValues: T): T { | ||
if (typeof values === 'undefined') { | ||
return defaultValues | ||
} | ||
|
||
if (!isValidObject(values)) { | ||
return values | ||
} | ||
|
||
if (!isValidObject(defaultValues)) { | ||
return values | ||
} | ||
|
||
return unique(Object.keys(defaultValues).concat(Object.keys(values))) | ||
.reduce((acc, key) => ({...acc, [key]: merge(values?.[key], defaultValues?.[key])}), {}) as T | ||
} | ||
|
||
export function solveLocale<L extends Labels> ( | ||
locale: Localized<L>, | ||
lang: string = navigator.language || DEFAULT_LANGUAGE | ||
): L { | ||
if (!isValidObject(locale)) { | ||
return locale | ||
} | ||
return Object.entries(locale).reduce((acc, [key, entry]) => { | ||
acc[key as keyof L] = (isLocaliedText(entry) ? getLocalizedText(entry, lang) : solveLocale(entry, lang)) as L[keyof L] | ||
return acc | ||
}, {} as L) | ||
} | ||
|
||
export function mergeLabels <L extends Labels> (labels?: L, defaultLabels?: L): L | undefined { | ||
return merge(labels, defaultLabels) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.