diff --git a/packages/angular-material/src/library/layouts/array-layout.renderer.ts b/packages/angular-material/src/library/layouts/array-layout.renderer.ts index 9cf7b6c9a..9f8850600 100644 --- a/packages/angular-material/src/library/layouts/array-layout.renderer.ts +++ b/packages/angular-material/src/library/layouts/array-layout.renderer.ts @@ -33,10 +33,13 @@ import { JsonFormsAbstractControl, } from '@jsonforms/angular'; import { + arrayDefaultTranslations, ArrayLayoutProps, ArrayTranslations, createDefaultValue, + defaultJsonFormsI18nState, findUISchema, + getArrayTranslations, isObjectArrayWithNesting, JsonFormsState, mapDispatchToArrayControlProps, @@ -169,7 +172,7 @@ export class ArrayLayoutRenderer implements OnInit, OnDestroy { noData: boolean; - translations: ArrayTranslations; + translations: ArrayTranslations = {}; addItem: (path: string, value: any) => () => void; moveItemUp: (path: string, index: number) => () => void; moveItemDown: (path: string, index: number) => () => void; @@ -181,9 +184,19 @@ export class ArrayLayoutRenderer constructor(jsonFormsService: JsonFormsAngularService) { super(jsonFormsService); } - mapToProps(state: JsonFormsState): StatePropsOfArrayLayout { + mapToProps( + state: JsonFormsState + ): StatePropsOfArrayLayout & { translations: ArrayTranslations } { const props = mapStateToArrayLayoutProps(state, this.getOwnProps()); - return { ...props }; + const t = + state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate; + const translations = getArrayTranslations( + t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ); + return { ...props, translations }; } remove(index: number): void { this.removeItems(this.propsPath, [index])(); @@ -211,10 +224,12 @@ export class ArrayLayoutRenderer this.moveItemDown = moveDown; this.removeItems = removeItems; } - mapAdditionalProps(props: ArrayLayoutProps) { - this.translations = props.translations; + mapAdditionalProps( + props: ArrayLayoutProps & { translations: ArrayTranslations } + ) { this.noData = !props.data || props.data === 0; this.uischemas = props.uischemas; + this.translations = props.translations; } getProps(index: number): OwnPropsOfRenderer { const uischema = findUISchema( diff --git a/packages/angular-material/src/library/other/master-detail/master.ts b/packages/angular-material/src/library/other/master-detail/master.ts index 4669f9d3f..d50d4f092 100644 --- a/packages/angular-material/src/library/other/master-detail/master.ts +++ b/packages/angular-material/src/library/other/master-detail/master.ts @@ -36,11 +36,14 @@ import { } from '@jsonforms/angular'; import { ArrayControlProps, + arrayDefaultTranslations, ArrayTranslations, ControlElement, createDefaultValue, decode, + defaultJsonFormsI18nState, findUISchema, + getArrayTranslations, getFirstPrimitiveProp, JsonFormsState, mapDispatchToArrayControlProps, @@ -194,7 +197,9 @@ export class MasterListComponent this.removeItems = removeItems; } - mapAdditionalProps(props: ArrayControlProps) { + mapAdditionalProps( + props: ArrayControlProps & { translations: ArrayTranslations } + ) { const { data, path, schema, uischema } = props; const controlElement = uischema as ControlElement; this.propsPath = props.path; @@ -282,9 +287,19 @@ export class MasterListComponent this.removeItems(this.propsPath, [item])(); } - protected mapToProps(state: JsonFormsState): StatePropsOfArrayControl { + protected mapToProps( + state: JsonFormsState + ): StatePropsOfArrayControl & { translations: ArrayTranslations } { const props = mapStateToArrayControlProps(state, this.getOwnProps()); - return { ...props }; + const t = + state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate; + const translations = getArrayTranslations( + t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ); + return { ...props, translations }; } } diff --git a/packages/angular-material/src/library/other/table.renderer.ts b/packages/angular-material/src/library/other/table.renderer.ts index 5f38a9f6a..3be3d7aaa 100644 --- a/packages/angular-material/src/library/other/table.renderer.ts +++ b/packages/angular-material/src/library/other/table.renderer.ts @@ -158,7 +158,7 @@ export class TableRenderer extends JsonFormsArrayControl implements OnInit { moveItemUp: (path: string, index: number) => () => void; moveItemDown: (path: string, index: number) => () => void; removeItems: (path: string, toDelete: number[]) => () => void; - translations: ArrayTranslations; + translations: ArrayTranslations = {}; constructor(jsonformsService: JsonFormsAngularService) { super(jsonformsService); @@ -166,7 +166,9 @@ export class TableRenderer extends JsonFormsArrayControl implements OnInit { trackElement(index: number, _element: any) { return index ? index : null; } - mapAdditionalProps(props: ArrayControlProps) { + mapAdditionalProps( + props: ArrayControlProps & { translations: ArrayTranslations } + ) { this.items = this.generateCells(props.schema, props.path); this.displayedColumns = this.items.map((item) => item.property); if (this.isEnabled()) { diff --git a/packages/angular/src/library/array-control.ts b/packages/angular/src/library/array-control.ts index 013f6cd61..5e0bfbc5e 100644 --- a/packages/angular/src/library/array-control.ts +++ b/packages/angular/src/library/array-control.ts @@ -23,6 +23,10 @@ THE SOFTWARE. */ import { + arrayDefaultTranslations, + ArrayTranslations, + defaultJsonFormsI18nState, + getArrayTranslations, JsonFormsState, mapStateToArrayControlProps, StatePropsOfArrayControl, @@ -34,8 +38,18 @@ export class JsonFormsArrayControl extends JsonFormsAbstractControl implements OnInit, OnDestroy { - protected mapToProps(state: JsonFormsState): StatePropsOfArrayControl { + protected mapToProps( + state: JsonFormsState + ): StatePropsOfArrayControl & { translations: ArrayTranslations } { const props = mapStateToArrayControlProps(state, this.getOwnProps()); - return { ...props }; + const t = + state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate; + const translations = getArrayTranslations( + t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ); + return { ...props, translations }; } } diff --git a/packages/core/src/mappers/renderer.ts b/packages/core/src/mappers/renderer.ts index 60e8adfca..fabdaa607 100644 --- a/packages/core/src/mappers/renderer.ts +++ b/packages/core/src/mappers/renderer.ts @@ -47,13 +47,8 @@ import { getI18nKey, getI18nKeyPrefix, getI18nKeyPrefixBySchema, - getArrayTranslations, - CombinatorTranslations, - getCombinatorTranslations, - combinatorDefaultTranslations, getTranslator, getErrorTranslator, - arrayDefaultTranslations, ArrayTranslations, } from '../i18n'; import cloneDeep from 'lodash/cloneDeep'; @@ -789,7 +784,6 @@ export interface ControlWithDetailProps */ export interface StatePropsOfArrayControl extends StatePropsOfControlWithDetail { - translations: ArrayTranslations; childErrors?: ErrorObject[]; } @@ -804,12 +798,11 @@ export const mapStateToArrayControlProps = ( state: JsonFormsState, ownProps: OwnPropsOfControl ): StatePropsOfArrayControl => { - const { path, schema, uischema, i18nKeyPrefix, label, ...props } = + const { path, schema, uischema, label, ...props } = mapStateToControlWithDetailProps(state, ownProps); const resolvedSchema = Resolve.schema(schema, 'items', props.rootSchema); const childErrors = getSubErrorsAt(path, resolvedSchema)(state); - const t = getTranslator()(state); return { ...props, @@ -820,12 +813,6 @@ export const mapStateToArrayControlProps = ( childErrors, renderers: ownProps.renderers || getRenderers(state), cells: ownProps.cells || getCells(state), - translations: getArrayTranslations( - t, - arrayDefaultTranslations, - i18nKeyPrefix, - label - ), }; }; @@ -1060,7 +1047,6 @@ export interface StatePropsOfCombinator extends StatePropsOfControl { indexOfFittingSchema: number; uischemas: JsonFormsUISchemaRegistryEntry[]; data: any; - translations: CombinatorTranslations; } export const mapStateToCombinatorRendererProps = ( @@ -1072,13 +1058,6 @@ export const mapStateToCombinatorRendererProps = ( mapStateToControlProps(state, ownProps); const ajv = state.jsonforms.core.ajv; - const t = getTranslator()(state); - const translations = getCombinatorTranslations( - t, - combinatorDefaultTranslations, - i18nKeyPrefix, - label - ); const structuralKeywords = [ 'required', 'additionalProperties', @@ -1125,7 +1104,6 @@ export const mapStateToCombinatorRendererProps = ( label, indexOfFittingSchema, uischemas: getUISchemas(state), - translations, }; }; @@ -1160,7 +1138,6 @@ export const mapStateToOneOfProps = ( export interface StatePropsOfArrayLayout extends StatePropsOfControlWithDetail { data: number; - translations: ArrayTranslations; minItems?: number; disableRemove?: boolean; disableAdd?: boolean; @@ -1176,7 +1153,7 @@ export const mapStateToArrayLayoutProps = ( state: JsonFormsState, ownProps: OwnPropsOfControl ): StatePropsOfArrayLayout => { - const { path, schema, uischema, errors, i18nKeyPrefix, label, ...props } = + const { path, schema, uischema, errors, label, ...props } = mapStateToControlWithDetailProps(state, ownProps); const resolvedSchema = Resolve.schema(schema, 'items', props.rootSchema); @@ -1204,12 +1181,6 @@ export const mapStateToArrayLayoutProps = ( data: props.data ? props.data.length : 0, errors: allErrors, minItems: schema.minItems, - translations: getArrayTranslations( - t, - arrayDefaultTranslations, - i18nKeyPrefix, - label - ), }; }; diff --git a/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx b/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx index ba943d3f7..22cbc2229 100644 --- a/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx +++ b/packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx @@ -25,6 +25,7 @@ import { and, ArrayLayoutProps, + ArrayTranslations, composePaths, computeLabel, createDefaultValue, @@ -36,7 +37,9 @@ import { } from '@jsonforms/core'; import { JsonFormsDispatch, + withArrayTranslationProps, withJsonFormsArrayLayoutProps, + withTranslateProps, } from '@jsonforms/react'; import { Grid, List, Typography } from '@mui/material'; import map from 'lodash/map'; @@ -63,11 +66,11 @@ export const MaterialListWithDetailRenderer = ({ cells, config, rootSchema, - translations, description, disableAdd, disableRemove, -}: ArrayLayoutProps) => { + translations, +}: ArrayLayoutProps & { translations: ArrayTranslations }) => { const [selectedIndex, setSelectedIndex] = useState(undefined); const handleRemoveItem = useCallback( (p: string, value: any) => () => { @@ -101,6 +104,7 @@ export const MaterialListWithDetailRenderer = ({ ), [uischemas, schema, uischema.scope, path, uischema, rootSchema] ); + const appliedUiSchemaOptions = merge({}, config, uischema.options); const doDisableAdd = disableAdd || appliedUiSchemaOptions.disableAdd; const doDisableRemove = disableRemove || appliedUiSchemaOptions.disableRemove; @@ -179,4 +183,6 @@ export const materialListWithDetailTester: RankedTester = rankWith( and(uiTypeIs('ListWithDetail'), isObjectArray) ); -export default withJsonFormsArrayLayoutProps(MaterialListWithDetailRenderer); +export default withJsonFormsArrayLayoutProps( + withTranslateProps(withArrayTranslationProps(MaterialListWithDetailRenderer)) +); diff --git a/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx b/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx index 346312b71..8906ccbbb 100644 --- a/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx +++ b/packages/material-renderers/src/complex/MaterialArrayControlRenderer.tsx @@ -25,21 +25,28 @@ import React, { useCallback, useState } from 'react'; import { ArrayLayoutProps, + ArrayTranslations, RankedTester, isObjectArrayControl, isPrimitiveArrayControl, or, rankWith, } from '@jsonforms/core'; -import { withJsonFormsArrayLayoutProps } from '@jsonforms/react'; +import { + withArrayTranslationProps, + withJsonFormsArrayLayoutProps, + withTranslateProps, +} from '@jsonforms/react'; import { MaterialTableControl } from './MaterialTableControl'; import { DeleteDialog } from './DeleteDialog'; -export const MaterialArrayControlRenderer = (props: ArrayLayoutProps) => { +export const MaterialArrayControlRenderer = ( + props: ArrayLayoutProps & { translations: ArrayTranslations } +) => { const [open, setOpen] = useState(false); const [path, setPath] = useState(undefined); const [rowData, setRowData] = useState(undefined); - const { removeItems, visible } = props; + const { removeItems, visible, translations } = props; const openDeleteDialog = useCallback( (p: string, rowIndex: number) => { @@ -63,16 +70,20 @@ export const MaterialArrayControlRenderer = (props: ArrayLayoutProps) => { return ( <> - + ); @@ -83,4 +94,6 @@ export const materialArrayControlTester: RankedTester = rankWith( or(isObjectArrayControl, isPrimitiveArrayControl) ); -export default withJsonFormsArrayLayoutProps(MaterialArrayControlRenderer); +export default withJsonFormsArrayLayoutProps( + withTranslateProps(withArrayTranslationProps(MaterialArrayControlRenderer)) +); diff --git a/packages/material-renderers/src/complex/MaterialTableControl.tsx b/packages/material-renderers/src/complex/MaterialTableControl.tsx index e221894a8..00239fc6c 100644 --- a/packages/material-renderers/src/complex/MaterialTableControl.tsx +++ b/packages/material-renderers/src/complex/MaterialTableControl.tsx @@ -451,7 +451,8 @@ const TableRows = ({ }; export class MaterialTableControl extends React.Component< - ArrayLayoutProps & WithDeleteDialogSupport, + ArrayLayoutProps & + WithDeleteDialogSupport & { translations: ArrayTranslations }, any > { addItem = (path: string, value: any) => this.props.addItem(path, value); diff --git a/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx b/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx index 6cec1d884..6846fd421 100644 --- a/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx +++ b/packages/material-renderers/src/layouts/MaterialArrayLayout.tsx @@ -26,6 +26,7 @@ import range from 'lodash/range'; import React, { useState, useCallback } from 'react'; import { ArrayLayoutProps, + ArrayTranslations, composePaths, computeLabel, createDefaultValue, @@ -35,7 +36,9 @@ import { ArrayLayoutToolbar } from './ArrayToolbar'; import ExpandPanelRenderer from './ExpandPanelRenderer'; import merge from 'lodash/merge'; -const MaterialArrayLayoutComponent = (props: ArrayLayoutProps) => { +const MaterialArrayLayoutComponent = ( + props: ArrayLayoutProps & { translations: ArrayTranslations } +) => { const [expanded, setExpanded] = useState(false); const innerCreateDefaultValue = useCallback( () => createDefaultValue(props.schema, props.rootSchema), @@ -65,10 +68,10 @@ const MaterialArrayLayoutComponent = (props: ArrayLayoutProps) => { rootSchema, config, uischemas, - translations, description, disableAdd, disableRemove, + translations, } = props; const appliedUiSchemaOptions = merge({}, config, props.uischema.options); const doDisableAdd = disableAdd || appliedUiSchemaOptions.disableAdd; diff --git a/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx b/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx index d68430143..2fd1001e2 100644 --- a/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx +++ b/packages/material-renderers/src/layouts/MaterialArrayLayoutRenderer.tsx @@ -26,29 +26,39 @@ import React, { useCallback } from 'react'; import { ArrayLayoutProps, + ArrayTranslations, isObjectArrayWithNesting, RankedTester, rankWith, } from '@jsonforms/core'; import { MaterialArrayLayout } from './MaterialArrayLayout'; -import { withJsonFormsArrayLayoutProps } from '@jsonforms/react'; +import { + withArrayTranslationProps, + withJsonFormsArrayLayoutProps, + withTranslateProps, +} from '@jsonforms/react'; export const MaterialArrayLayoutRenderer = ({ visible, addItem, + translations, ...props -}: ArrayLayoutProps) => { +}: ArrayLayoutProps & { translations: ArrayTranslations }) => { const addItemCb = useCallback( (p: string, value: any) => addItem(p, value), [addItem] ); - if (!visible) { return null; } return ( - + ); }; @@ -56,4 +66,6 @@ export const materialArrayLayoutTester: RankedTester = rankWith( 4, isObjectArrayWithNesting ); -export default withJsonFormsArrayLayoutProps(MaterialArrayLayoutRenderer); +export default withJsonFormsArrayLayoutProps( + withTranslateProps(withArrayTranslationProps(MaterialArrayLayoutRenderer)) +); diff --git a/packages/react/src/JsonFormsContext.tsx b/packages/react/src/JsonFormsContext.tsx index 84752883a..72404dd8c 100644 --- a/packages/react/src/JsonFormsContext.tsx +++ b/packages/react/src/JsonFormsContext.tsx @@ -78,6 +78,9 @@ import { CoreActions, Middleware, defaultMiddleware, + arrayDefaultTranslations, + getArrayTranslations, + ArrayTranslations, } from '@jsonforms/core'; import debounce from 'lodash/debounce'; import React, { @@ -889,3 +892,22 @@ export const withTranslateProps =

( return ; }; + +export const withArrayTranslationProps = < + P extends ArrayLayoutProps & TranslateProps +>( + Component: ComponentType

+) => + function withArrayTranslatationProps(props: P) { + const translations = useMemo( + () => + getArrayTranslations( + props.t, + arrayDefaultTranslations, + props.i18nKeyPrefix, + props.label + ), + [props.t, props.i18nKeyPrefix, props.label] + ); + return ; + }; diff --git a/packages/vanilla-renderers/src/complex/TableArrayControl.tsx b/packages/vanilla-renderers/src/complex/TableArrayControl.tsx index 1850b631a..86683930b 100644 --- a/packages/vanilla-renderers/src/complex/TableArrayControl.tsx +++ b/packages/vanilla-renderers/src/complex/TableArrayControl.tsx @@ -41,8 +41,14 @@ import { Test, getControlPath, encode, + ArrayTranslations, } from '@jsonforms/core'; -import { DispatchCell, withJsonFormsArrayControlProps } from '@jsonforms/react'; +import { + DispatchCell, + withArrayTranslationProps, + withJsonFormsArrayControlProps, + withTranslateProps, +} from '@jsonforms/react'; import { withVanillaControlProps } from '../util'; import type { VanillaRendererProps } from '../index'; @@ -61,7 +67,8 @@ export const tableArrayControlTester: RankedTester = rankWith( ); class TableArrayControl extends React.Component< - ArrayControlProps & VanillaRendererProps, + ArrayControlProps & + VanillaRendererProps & { translations: ArrayTranslations }, any > { confirmDelete = (path: string, index: number) => { @@ -239,6 +246,8 @@ class TableArrayControl extends React.Component< } } -export default withVanillaControlProps( - withJsonFormsArrayControlProps(TableArrayControl) +export default withTranslateProps( + withVanillaControlProps( + withJsonFormsArrayControlProps(withArrayTranslationProps(TableArrayControl)) + ) ); diff --git a/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx b/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx index 884cfe586..cf7df7cce 100644 --- a/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx +++ b/packages/vanilla-renderers/src/complex/array/ArrayControlRenderer.tsx @@ -31,10 +31,13 @@ import { findUISchema, Helpers, ControlElement, + ArrayTranslations, } from '@jsonforms/core'; import { JsonFormsDispatch, + withArrayTranslationProps, withJsonFormsArrayControlProps, + withTranslateProps, } from '@jsonforms/react'; import type { VanillaRendererProps } from '../../index'; import { withVanillaControlProps } from '../../util'; @@ -58,7 +61,8 @@ export const ArrayControl = ({ renderers, rootSchema, translations, -}: ArrayControlProps & VanillaRendererProps) => { +}: ArrayControlProps & + VanillaRendererProps & { translations: ArrayTranslations }) => { const controlElement = uischema as ControlElement; const childUiSchema = useMemo( () => @@ -184,7 +188,8 @@ export const ArrayControlRenderer = ({ enabled, errors, translations, -}: ArrayControlProps & VanillaRendererProps) => { +}: ArrayControlProps & + VanillaRendererProps & { translations: ArrayTranslations }) => { const controlElement = uischema as ControlElement; const labelDescription = Helpers.createLabelDescriptionFrom( controlElement, @@ -229,6 +234,10 @@ export const ArrayControlRenderer = ({ ); }; -export default withVanillaControlProps( - withJsonFormsArrayControlProps(ArrayControlRenderer) +export default withTranslateProps( + withVanillaControlProps( + withJsonFormsArrayControlProps( + withArrayTranslationProps(ArrayControlRenderer) + ) + ) );