From 0d113185078336aaad551889ada5ebc1e3f3d776 Mon Sep 17 00:00:00 2001 From: LukasBoll Date: Tue, 28 Feb 2023 00:27:28 +0100 Subject: [PATCH] Apply suggestions from code review Co-authored-by: Lucas Koehler --- packages/core/src/i18n/arrayTranslations.ts | 20 ++-- packages/core/src/i18n/i18nUtil.ts | 14 +-- packages/core/src/i18n/index.ts | 1 + packages/core/src/util/renderer.ts | 6 +- packages/examples/src/examples/arraysI18n.ts | 112 ++++++++++++++++++ packages/examples/src/index.ts | 2 + .../src/complex/DeleteDialog.tsx | 14 +-- .../complex/MaterialArrayControlRenderer.tsx | 4 +- .../src/complex/MaterialTableControl.tsx | 2 +- .../src/complex/TableToolbar.tsx | 2 +- .../src/layouts/ArrayToolbar.tsx | 2 +- 11 files changed, 145 insertions(+), 34 deletions(-) create mode 100644 packages/examples/src/examples/arraysI18n.ts diff --git a/packages/core/src/i18n/arrayTranslations.ts b/packages/core/src/i18n/arrayTranslations.ts index cc5da793c..1ae47f0ff 100644 --- a/packages/core/src/i18n/arrayTranslations.ts +++ b/packages/core/src/i18n/arrayTranslations.ts @@ -1,4 +1,4 @@ -export interface DefaultTranslation { +export interface ArrayDefaultTranslation { key: ArrayTranslationEnum, default: (variable?: string) => string } @@ -12,8 +12,8 @@ export enum ArrayTranslationEnum{ noSelection = 'noSelection', removeAriaLabel = 'removeAriaLabel', noDataMessage = 'noDataMessage', - deleteDialogHeader = 'deleteDialogHeader', - deleteDialogMsg = 'deleteDialogMsg', + deleteDialogTitle = 'deleteDialogTitle', + deleteDialogMessage = 'deleteDialogMessage', deleteDialogAccept = 'deleteDialogAccept', deleteDialogDecline = 'deleteDialogDecline' } @@ -22,7 +22,7 @@ export type ArrayTranslations = { [key in ArrayTranslationEnum]?: string } -export const arrayDefaultTranslations: DefaultTranslation[] = [ +export const arrayDefaultTranslations: ArrayDefaultTranslation[] = [ {key: ArrayTranslationEnum.addTooltip, default: (input) => input?`Add to ${input}`:'Add'}, {key: ArrayTranslationEnum.addAriaLabel, default: (input) => input?`Add to ${input}`:'Add'}, {key: ArrayTranslationEnum.removeTooltip, default: () => 'Delete'}, @@ -31,10 +31,8 @@ export const arrayDefaultTranslations: DefaultTranslation[] = [ {key: ArrayTranslationEnum.removeAriaLabel, default: () => 'Delete button'}, {key: ArrayTranslationEnum.noDataMessage, default: () => 'No Data'}, {key: ArrayTranslationEnum.noSelection, default: () => 'No Selection'}, - {key: ArrayTranslationEnum.deleteDialogHeader, default: () => 'Confirm Deletion'}, - {key: ArrayTranslationEnum.deleteDialogMsg, default: () => 'Are you sure you want to delete the selected entry?'}, - {key: ArrayTranslationEnum.deleteDialogAccept, default: () => 'YES'}, - {key: ArrayTranslationEnum.deleteDialogDecline, default: () => 'NO'} -] - -export const arrayTranslations: DefaultTranslation[] = Object.values(arrayDefaultTranslations).map(value=>value); \ No newline at end of file + {key: ArrayTranslationEnum.deleteDialogTitle, default: () => 'Confirm Deletion'}, + {key: ArrayTranslationEnum.deleteDialogMessage, default: () => 'Are you sure you want to delete the selected entry?'}, + {key: ArrayTranslationEnum.deleteDialogAccept, default: () => 'Yes'}, + {key: ArrayTranslationEnum.deleteDialogDecline, default: () => 'No'} +] \ No newline at end of file diff --git a/packages/core/src/i18n/i18nUtil.ts b/packages/core/src/i18n/i18nUtil.ts index ecf258654..626a0d087 100644 --- a/packages/core/src/i18n/i18nUtil.ts +++ b/packages/core/src/i18n/i18nUtil.ts @@ -3,7 +3,7 @@ import { isInternationalized, Labelable, UISchemaElement } from '../models'; import { getControlPath } from '../reducers'; import { formatErrorMessage } from '../util'; import type { i18nJsonSchema, ErrorTranslator, Translator } from './i18nTypes'; -import { DefaultTranslation, ArrayTranslations } from './arrayTranslations' +import { ArrayDefaultTranslation, ArrayTranslations } from './arrayTranslations' export const getI18nKeyPrefixBySchema = ( schema: i18nJsonSchema | undefined, @@ -49,10 +49,10 @@ export const getI18nKey = ( }; export const addI18nKeyToPrefix = ( - I18nKeyPrefix: string, + i18nKeyPrefix: string, key: string ): string => { - return `${I18nKeyPrefix}.${key}`; + return `${i18nKeyPrefix}.${key}`; }; export const defaultTranslator: Translator = (_id: string, defaultMessage: string | undefined) => defaultMessage; @@ -132,18 +132,16 @@ export const deriveLabelForUISchemaElement = (uischema: Labelable, t: T return t(i18nKey, stringifiedLabel, { uischema: uischema }); } -export const translateElements = ( +export const getArrayTranslations = ( t: Translator, - controlElements: DefaultTranslation [], + defaultTranslations: ArrayDefaultTranslation [], i18nKeyPrefix: string, label: string ): ArrayTranslations => { const translations:ArrayTranslations = {}; - console.log("translating..."); - controlElements.forEach((controlElement)=>{ + defaultTranslations.forEach((controlElement)=>{ const key = addI18nKeyToPrefix(i18nKeyPrefix, controlElement.key); translations[controlElement.key]=t(key, controlElement.default(label)); - console.log("translations: ", translations); }) return translations; } diff --git a/packages/core/src/i18n/index.ts b/packages/core/src/i18n/index.ts index 298d5f4d5..fb4cc88d9 100644 --- a/packages/core/src/i18n/index.ts +++ b/packages/core/src/i18n/index.ts @@ -1,2 +1,3 @@ export * from './i18nTypes'; export * from './i18nUtil'; +export * from './arrayTranslations' \ No newline at end of file diff --git a/packages/core/src/util/renderer.ts b/packages/core/src/util/renderer.ts index 3d7f664dd..d4cddd0d6 100644 --- a/packages/core/src/util/renderer.ts +++ b/packages/core/src/util/renderer.ts @@ -56,7 +56,7 @@ import { composePaths, composeWithUi } from './path'; import { CoreActions, update } from '../actions'; import type { ErrorObject } from 'ajv'; import type { JsonFormsState } from '../store'; -import { deriveLabelForUISchemaElement, getCombinedErrorMessage, getI18nKey, getI18nKeyPrefix, getI18nKeyPrefixBySchema, translateElements, Translator } from '../i18n'; +import { deriveLabelForUISchemaElement, getCombinedErrorMessage, getI18nKey, getI18nKeyPrefix, getI18nKeyPrefixBySchema, getArrayTranslations, Translator } from '../i18n'; import { arrayDefaultTranslations, ArrayTranslations } from '../i18n/arrayTranslations'; const isRequired = ( @@ -1017,8 +1017,8 @@ export const mapStateToOneOfProps = ( export interface StatePropsOfArrayLayout extends StatePropsOfControlWithDetail { data: number; + translations: ArrayTranslations; minItems?: number; - translations?: ArrayTranslations; } /** * Map state to table props @@ -1067,7 +1067,7 @@ export const mapStateToArrayLayoutProps = ( data: props.data ? props.data.length : 0, errors: allErrors, minItems: schema.minItems, - translations: translateElements(t,arrayDefaultTranslations,i18nKeyPrefix, label) + translations: getArrayTranslations(t,arrayDefaultTranslations,i18nKeyPrefix, label) }; }; diff --git a/packages/examples/src/examples/arraysI18n.ts b/packages/examples/src/examples/arraysI18n.ts new file mode 100644 index 000000000..cb9ef81be --- /dev/null +++ b/packages/examples/src/examples/arraysI18n.ts @@ -0,0 +1,112 @@ +/* + The MIT License + + Copyright (c) 2017-2019 EclipseSource Munich + https://github.com/eclipsesource/jsonforms + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +import { registerExamples } from '../register'; +import { ArrayTranslationEnum, Translator } from '@jsonforms/core'; +import { get } from 'lodash'; + +export const schema = { + type: 'object', + properties: { + comments: { + type: 'array', + items: { + type: 'object', + properties: { + date: { + type: 'string', + format: 'date' + }, + message: { + type: 'string', + maxLength: 5 + }, + enum: { + type: 'string', + const: 'foo' + } + } + } + }, + foo:{type:'string'} + } +}; + +export const uischema = { + type: 'VerticalLayout', + elements: [ + { + type: 'Control', + scope: '#/properties/foo' + }, + { + type: 'Control', + scope: '#/properties/comments', + options: { + showSortButtons: true, + } + } + ] +}; + +export const data = { + comments: [ + { + date: new Date(2001, 8, 11).toISOString().substr(0, 10), + message: 'This is an example message' + }, + { + date: new Date().toISOString().substr(0, 10), + message: 'Get ready for booohay' + } + ] +}; + +export const translations = { + comments: { + [ArrayTranslationEnum.noDataMessage]: 'Be the first to write a comment', + [ArrayTranslationEnum.addTooltip]: 'Add a Comment', + [ArrayTranslationEnum.deleteDialogAccept]: 'Delete!', + [ArrayTranslationEnum.deleteDialogDecline]: 'Cancel!', + [ArrayTranslationEnum.deleteDialogMessage]: 'Are you sure you want to delete this comment?' + } +}; +export const translate: Translator = (key: string, defaultMessage: string) => { + console.log(key); + return get(translations, key) ?? defaultMessage; +}; + +registerExamples([ + { + name: 'array (i18n)', + label: 'Array (i18n)', + data, + schema, + uischema, + i18n: { + translate: translate, + locale: 'en' + } + } +]); diff --git a/packages/examples/src/index.ts b/packages/examples/src/index.ts index d27050a3c..a9b955b2e 100644 --- a/packages/examples/src/index.ts +++ b/packages/examples/src/index.ts @@ -28,6 +28,7 @@ import * as oneOf from './examples/oneOf'; import * as oneOfArray from './examples/oneOfArray'; import * as anyOfOneOfAllOfResolve from './examples/anyOf-oneOf-allOf-resolve'; import * as array from './examples/arrays'; +import * as arrayI18n from './examples/arraysI18n'; import * as nestedArray from './examples/nestedArrays'; import * as arrayWithDetail from './examples/arrays-with-detail'; import * as arrayWithDetailAndRule from './examples/arrays-with-detail-and-rule'; @@ -97,6 +98,7 @@ export { anyOfOneOfAllOfResolve, stringArray, array, + arrayI18n, nestedArray, arrayWithDetail, arrayWithDetailAndRule, diff --git a/packages/material-renderers/src/complex/DeleteDialog.tsx b/packages/material-renderers/src/complex/DeleteDialog.tsx index 1499b0fd6..24ad8f037 100644 --- a/packages/material-renderers/src/complex/DeleteDialog.tsx +++ b/packages/material-renderers/src/complex/DeleteDialog.tsx @@ -37,8 +37,8 @@ export interface DeleteDialogProps { onClose(): void; onConfirm(): void; onCancel(): void; - headerText: string, - msg: string, + title: string, + message: string, acceptText: string, declineText: string } @@ -47,7 +47,7 @@ export interface WithDeleteDialogSupport { openDeleteDialog(path: string, data: number): void; } -export const DeleteDialog = React.memo(({ open, onClose, onConfirm, onCancel, headerText: header, msg, acceptText: accept, declineText: decline }: DeleteDialogProps) => { +export const DeleteDialog = React.memo(({ open, onClose, onConfirm, onCancel, title, message, acceptText, declineText }: DeleteDialogProps) => { return ( - {header} + {title} - {msg} + {message} diff --git a/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx b/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx index 643c46ffd..40019de71 100644 --- a/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx +++ b/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx @@ -61,8 +61,8 @@ export const MaterialArrayControlRenderer = (props: ArrayLayoutProps) => { onClose={deleteClose} acceptText={props.translations.deleteDialogAccept} declineText={props.translations.deleteDialogDecline} - headerText={props.translations.deleteDialogHeader} - msg={props.translations.deleteDialogMsg} + title={props.translations.deleteDialogTitle} + message={props.translations.deleteDialogMessage} /> ); diff --git a/packages/material-renderers/src/complex/MaterialTableControl.tsx b/packages/material-renderers/src/complex/MaterialTableControl.tsx index 697075a19..c248f74c3 100644 --- a/packages/material-renderers/src/complex/MaterialTableControl.tsx +++ b/packages/material-renderers/src/complex/MaterialTableControl.tsx @@ -65,7 +65,7 @@ import NoBorderTableCell from './NoBorderTableCell'; import TableToolbar from './TableToolbar'; import { ErrorObject } from 'ajv'; import merge from 'lodash/merge'; -import { ArrayTranslations } from '@jsonforms/core/lib/i18n/arrayTranslations'; +import { ArrayTranslations } from '@jsonforms/core'; // we want a cell that doesn't automatically span const styles = { diff --git a/packages/material-renderers/src/complex/TableToolbar.tsx b/packages/material-renderers/src/complex/TableToolbar.tsx index 3516f2958..2611965b5 100644 --- a/packages/material-renderers/src/complex/TableToolbar.tsx +++ b/packages/material-renderers/src/complex/TableToolbar.tsx @@ -37,7 +37,7 @@ import { Grid, Typography } from '@mui/material'; import AddIcon from '@mui/icons-material/Add'; import ValidationIcon from './ValidationIcon'; import NoBorderTableCell from './NoBorderTableCell'; -import { ArrayTranslations } from '@jsonforms/core/lib/i18n/arrayTranslations'; +import { ArrayTranslations } from '@jsonforms/core'; export interface MaterialTableToolbarProps { numColumns: number; diff --git a/packages/material-renderers/src/layouts/ArrayToolbar.tsx b/packages/material-renderers/src/layouts/ArrayToolbar.tsx index 5caf1ef20..3ab27851f 100644 --- a/packages/material-renderers/src/layouts/ArrayToolbar.tsx +++ b/packages/material-renderers/src/layouts/ArrayToolbar.tsx @@ -8,7 +8,7 @@ import { import AddIcon from '@mui/icons-material/Add'; import React from 'react'; import ValidationIcon from '../complex/ValidationIcon'; -import { ArrayTranslations } from '@jsonforms/core/lib/i18n/arrayTranslations'; +import { ArrayTranslations } from '@jsonforms/core'; export interface ArrayLayoutToolbarProps { label: string; errors: string;