Skip to content

Commit 8b6c9d2

Browse files
authored
Array translations for react vanilla, angular-material, vue (#2129)
Replace existing hard-coded labels with translation-options for array-control elements for the vanilla, angular-material and vue renderers.
1 parent 06bbb4b commit 8b6c9d2

File tree

20 files changed

+105
-88
lines changed

20 files changed

+105
-88
lines changed

packages/angular-material/src/layouts/array-layout.renderer.ts

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
import { JsonFormsAngularService, JsonFormsAbstractControl } from '@jsonforms/angular';
3232
import {
3333
ArrayLayoutProps,
34+
ArrayTranslations,
3435
createDefaultValue,
3536
findUISchema,
3637
isObjectArrayWithNesting,
@@ -68,15 +69,15 @@ import {
6869
<span fxFlex></span>
6970
<button
7071
mat-button
71-
matTooltip="{{ this.addTooltip }}"
72+
matTooltip="{{ translations.addTooltip }}"
7273
[disabled]="!isEnabled()"
7374
(click)="add()"
74-
attr.aria-label="{{ this.addAriaLabel }}"
75+
attr.aria-label="{{ translations.addAriaLabel }}"
7576
>
7677
<mat-icon>add</mat-icon>
7778
</button>
7879
</div>
79-
<p *ngIf="noData">{{ this.noDataMessage }}</p>
80+
<p *ngIf="noData">{{ translations.noDataMessage }}</p>
8081
<div
8182
*ngFor="
8283
let item of [].constructor(data);
@@ -97,8 +98,8 @@ import {
9798
mat-button
9899
[disabled]="first"
99100
(click)="up(idx)"
100-
attr.aria-label="{{ this.upAriaLabel }}"
101-
matTooltip="{{ this.upTooltip }}"
101+
attr.aria-label="{{ translations.upAriaLabel }}"
102+
matTooltip="{{ translations.up }}"
102103
matTooltipPosition="right"
103104
>
104105
<mat-icon>arrow_upward</mat-icon>
@@ -109,8 +110,8 @@ import {
109110
mat-button
110111
[disabled]="last"
111112
(click)="down(idx)"
112-
attr.aria-label="{{ this.downAriaLabel }}"
113-
matTooltip="{{ this.downTooltip }}"
113+
attr.aria-label="{{ translations.downAriaLabel }}"
114+
matTooltip="{{ translations.down }}"
114115
matTooltipPosition="right"
115116
>
116117
<mat-icon>arrow_downward</mat-icon>
@@ -119,8 +120,8 @@ import {
119120
mat-button
120121
color="warn"
121122
(click)="remove(idx)"
122-
attr.aria-label="{{ this.removeAriaLabel }}"
123-
matTooltip="{{ this.removeTooltip }}"
123+
attr.aria-label="{{ translations.removeAriaLabel }}"
124+
matTooltip="{{ translations.removeTooltip }}"
124125
matTooltipPosition="right"
125126
>
126127
<mat-icon>delete</mat-icon>
@@ -148,16 +149,8 @@ import {
148149
export class ArrayLayoutRenderer
149150
extends JsonFormsAbstractControl<StatePropsOfArrayLayout>
150151
implements OnInit, OnDestroy {
151-
addTooltip: string;
152-
addAriaLabel: string;
153-
noDataMessage: string;
154-
removeTooltip: string;
155-
removeAriaLabel: string;
156-
upTooltip: string;
157-
upAriaLabel: string;
158-
downTooltip: string;
159-
downAriaLabel:string;
160152
noData: boolean;
153+
translations: ArrayTranslations;
161154
addItem: (path: string, value: any) => () => void;
162155
moveItemUp: (path: string, index: number) => () => void;
163156
moveItemDown: (path: string, index: number) => () => void;
@@ -196,15 +189,9 @@ export class ArrayLayoutRenderer
196189
this.removeItems = removeItems;
197190
}
198191
mapAdditionalProps(props: ArrayLayoutProps) {
192+
this.translations = props.translations;
199193
this.noData = !props.data || props.data === 0;
200194
this.uischemas = props.uischemas;
201-
this.addTooltip = `Add to ${this.label}`;
202-
this.addAriaLabel = `Add to ${this.label} button`;
203-
this.upAriaLabel = `Move ${this.label} up`;
204-
this.downAriaLabel = `Move ${this.label} down`;
205-
this.removeTooltip = `Delete`;
206-
this.removeAriaLabel = `Delete button`;
207-
this.noDataMessage = `No data`;
208195
}
209196
getProps(index: number): OwnPropsOfRenderer {
210197
const uischema = findUISchema(

packages/angular-material/src/other/master-detail/master.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import {
3131
} from '@jsonforms/angular';
3232
import {
3333
ArrayControlProps,
34+
ArrayTranslations,
3435
ControlElement,
3536
createDefaultValue,
3637
decode,
@@ -64,7 +65,7 @@ export const removeSchemaKeywords = (path: string) => {
6465
<mat-sidenav mode="side" opened>
6566
<mat-nav-list>
6667
<mat-list-item *ngIf="masterItems.length === 0"
67-
>No items</mat-list-item
68+
>{{ translations.noDataMessage }}</mat-list-item
6869
>
6970
<mat-list-item
7071
*ngFor="
@@ -96,7 +97,7 @@ export const removeSchemaKeywords = (path: string) => {
9697
(click)="onAddClick()"
9798
*ngIf="isEnabled()"
9899
>
99-
<mat-icon aria-label="Add item to list">add</mat-icon>
100+
<mat-icon [attr.aria-label]="translations.addAriaLabel">add</mat-icon>
100101
</button>
101102
</mat-sidenav>
102103
<mat-sidenav-content class="content">
@@ -149,6 +150,7 @@ export class MasterListComponent extends JsonFormsArrayControl {
149150
removeItems: (path: string, toDelete: number[]) => () => void;
150151
propsPath: string;
151152
highlightedIdx: number;
153+
translations: ArrayTranslations;
152154

153155
constructor(jsonformsService: JsonFormsAngularService, private changeDetectorRef: ChangeDetectorRef) {
154156
super(jsonformsService);
@@ -188,6 +190,8 @@ export class MasterListComponent extends JsonFormsArrayControl {
188190
setReadonly(detailUISchema);
189191
}
190192

193+
this.translations=props.translations;
194+
191195
const masterItems = (data || []).map((d: any, index: number) => {
192196
const labelRefInstancePath = controlElement.options?.labelRef && removeSchemaKeywords(
193197
controlElement.options.labelRef

packages/angular-material/src/other/table.renderer.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
} from '@jsonforms/angular';
3131
import {
3232
ArrayControlProps,
33+
ArrayTranslations,
3334
ControlElement, createDefaultValue,
3435
deriveTypes,
3536
encode,
@@ -57,7 +58,7 @@ import {
5758
<ng-container matColumnDef="action">
5859
<tr>
5960
<th mat-header-cell *matHeaderCellDef>
60-
<button mat-button color="primary" (click)="add()" [disabled]="!isEnabled()" matTooltip="Add"><mat-icon>add</mat-icon></button>
61+
<button mat-button color="primary" (click)="add()" [disabled]="!isEnabled()" [matTooltip]="translations.addTooltip"><mat-icon>add</mat-icon></button>
6162
</th>
6263
</tr>
6364
<tr>
@@ -68,7 +69,7 @@ import {
6869
mat-button
6970
[disabled]="first"
7071
(click)="up(i)"
71-
matTooltip="Move item up"
72+
[matTooltip]="translations.upAriaLabel"
7273
matTooltipPosition="right"
7374
>
7475
<mat-icon>arrow_upward</mat-icon>
@@ -79,7 +80,7 @@ import {
7980
mat-button
8081
[disabled]="last"
8182
(click)="down(i)"
82-
matTooltip="Move item down"
83+
[matTooltip]="translations.downAriaLabel"
8384
matTooltipPosition="right"
8485
>
8586
<mat-icon>arrow_downward</mat-icon>
@@ -90,7 +91,7 @@ import {
9091
(click)="remove(i)"
9192
[disabled]="!isEnabled()"
9293
matTooltipPosition="right"
93-
matTooltip="Delete"
94+
[matTooltip]="translations.removeTooltip"
9495
>
9596
<mat-icon>delete</mat-icon>
9697
</button>
@@ -126,6 +127,7 @@ export class TableRenderer extends JsonFormsArrayControl {
126127
moveItemUp: (path: string, index: number) => () => void;
127128
moveItemDown: (path: string, index: number) => () => void;
128129
removeItems: (path: string, toDelete: number[]) => () => void;
130+
translations: ArrayTranslations;
129131

130132
constructor(jsonformsService: JsonFormsAngularService) {
131133
super(jsonformsService);
@@ -139,6 +141,7 @@ export class TableRenderer extends JsonFormsArrayControl {
139141
if (this.isEnabled()) {
140142
this.displayedColumns.push('action');
141143
}
144+
this.translations = props.translations;
142145
}
143146
getProps(index: number, props: OwnPropsOfRenderer): OwnPropsOfRenderer {
144147
const rowPath = Paths.compose(props.path, `${index}`);

packages/angular-material/test/master-detail.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { MasterListComponent } from '../src/other/master-detail/master';
4141
import { JsonFormsDetailComponent } from '../src/other/master-detail/detail';
4242
import { getJsonFormsService, setupMockStore } from '@jsonforms/angular-test';
4343
import { Actions } from '@jsonforms/core';
44+
import { MatTooltipModule } from '@angular/material/tooltip';
4445

4546
describe('Master detail', () => {
4647
let fixture: ComponentFixture<MasterListComponent>;
@@ -114,7 +115,8 @@ describe('Master detail', () => {
114115
MatIconModule,
115116
MatButtonModule,
116117
FlexLayoutModule,
117-
NoopAnimationsModule
118+
NoopAnimationsModule,
119+
MatTooltipModule
118120
],
119121
providers: [JsonFormsAngularService]
120122
})

packages/angular-material/test/table-control.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import {
4242
import { FlexLayoutModule } from '@angular/flex-layout';
4343
import { setupMockStore } from '@jsonforms/angular-test';
4444
import { createTesterContext } from './util';
45+
import { MatTooltipModule } from '@angular/material/tooltip';
4546

4647
const uischema1: ControlElement = { type: 'Control', scope: '#' };
4748
const uischema2: ControlElement = {
@@ -127,7 +128,8 @@ describe('Table', () => {
127128
MatInputModule,
128129
ReactiveFormsModule,
129130
FlexLayoutModule,
130-
MatTableModule
131+
MatTableModule,
132+
MatTooltipModule,
131133
],
132134
providers: [JsonFormsAngularService]
133135
})

packages/core/src/i18n/arrayTranslations.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ export enum ArrayTranslationEnum{
1515
deleteDialogTitle = 'deleteDialogTitle',
1616
deleteDialogMessage = 'deleteDialogMessage',
1717
deleteDialogAccept = 'deleteDialogAccept',
18-
deleteDialogDecline = 'deleteDialogDecline'
18+
deleteDialogDecline = 'deleteDialogDecline',
19+
up = 'up',
20+
down = 'down'
1921
}
2022

2123
export type ArrayTranslations = {
@@ -24,13 +26,15 @@ export type ArrayTranslations = {
2426

2527
export const arrayDefaultTranslations: ArrayDefaultTranslation[] = [
2628
{key: ArrayTranslationEnum.addTooltip, default: (input) => input?`Add to ${input}`:'Add'},
27-
{key: ArrayTranslationEnum.addAriaLabel, default: (input) => input?`Add to ${input}`:'Add'},
29+
{key: ArrayTranslationEnum.addAriaLabel, default: (input) => input?`Add to ${input} button`:'Add button'},
2830
{key: ArrayTranslationEnum.removeTooltip, default: () => 'Delete'},
29-
{key: ArrayTranslationEnum.upAriaLabel, default: (input) => `Move ${input} up`},
30-
{key: ArrayTranslationEnum.downAriaLabel, default: (input) => `Move ${input} down`},
3131
{key: ArrayTranslationEnum.removeAriaLabel, default: () => 'Delete button'},
32-
{key: ArrayTranslationEnum.noDataMessage, default: () => 'No Data'},
33-
{key: ArrayTranslationEnum.noSelection, default: () => 'No Selection'},
32+
{key: ArrayTranslationEnum.upAriaLabel, default: () => `Move item up`},
33+
{key: ArrayTranslationEnum.up, default: () => 'Up'},
34+
{key: ArrayTranslationEnum.down, default: () => 'Down'},
35+
{key: ArrayTranslationEnum.downAriaLabel, default: () => `Move item down`},
36+
{key: ArrayTranslationEnum.noDataMessage, default: () => 'No data'},
37+
{key: ArrayTranslationEnum.noSelection, default: () => 'No selection'},
3438
{key: ArrayTranslationEnum.deleteDialogTitle, default: () => 'Confirm Deletion'},
3539
{key: ArrayTranslationEnum.deleteDialogMessage, default: () => 'Are you sure you want to delete the selected entry?'},
3640
{key: ArrayTranslationEnum.deleteDialogAccept, default: () => 'Yes'},

packages/core/src/util/renderer.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,7 @@ export interface OwnPropsOfMasterListItem {
652652
schema: JsonSchema;
653653
handleSelect(index: number): () => void;
654654
removeItem(path: string, value: number): () => void;
655+
translations: ArrayTranslations;
655656
}
656657

657658
export interface StatePropsOfMasterItem extends OwnPropsOfMasterListItem {
@@ -686,6 +687,7 @@ export interface ControlWithDetailProps
686687
*/
687688
export interface StatePropsOfArrayControl
688689
extends StatePropsOfControlWithDetail {
690+
translations: ArrayTranslations;
689691
childErrors?: ErrorObject[];
690692
}
691693

@@ -700,23 +702,25 @@ export const mapStateToArrayControlProps = (
700702
state: JsonFormsState,
701703
ownProps: OwnPropsOfControl
702704
): StatePropsOfArrayControl => {
703-
const { path, schema, uischema, ...props } = mapStateToControlWithDetailProps(
705+
const { path, schema, uischema, i18nKeyPrefix, label, ...props } = mapStateToControlWithDetailProps(
704706
state,
705707
ownProps
706708
);
707709

708710
const resolvedSchema = Resolve.schema(schema, 'items', props.rootSchema);
709711
const childErrors = getSubErrorsAt(path, resolvedSchema)(state);
710-
712+
const t = getTranslator()(state);
711713

712714
return {
713715
...props,
716+
label,
714717
path,
715718
uischema,
716719
schema: resolvedSchema,
717720
childErrors,
718721
renderers: ownProps.renderers || getRenderers(state),
719722
cells: ownProps.cells || getCells(state),
723+
translations: getArrayTranslations(t,arrayDefaultTranslations,i18nKeyPrefix, label)
720724
};
721725
};
722726

packages/material-renderers/src/additional/ListWithDetailMasterItem.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {
3535
import DeleteIcon from '@mui/icons-material/Delete';
3636
import React from 'react';
3737

38-
const ListWithDetailMasterItem = ({ index, childLabel, selected, handleSelect, removeItem, path }: StatePropsOfMasterItem) => {
38+
const ListWithDetailMasterItem = ({ index, childLabel, selected, handleSelect, removeItem, path, translations }: StatePropsOfMasterItem) => {
3939
return (
4040
<ListItem
4141
button
@@ -47,7 +47,7 @@ const ListWithDetailMasterItem = ({ index, childLabel, selected, handleSelect, r
4747
</ListItemAvatar>
4848
<ListItemText primary={childLabel} />
4949
<ListItemSecondaryAction>
50-
<IconButton aria-label='Delete' onClick={removeItem(path, index)} size='large'>
50+
<IconButton aria-label={translations.removeAriaLabel} onClick={removeItem(path, index)} size='large'>
5151
<DeleteIcon />
5252
</IconButton>
5353
</ListItemSecondaryAction>

packages/material-renderers/src/additional/MaterialListWithDetailRenderer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ export const MaterialListWithDetailRenderer = ({
130130
removeItem={handleRemoveItem}
131131
selected={selectedIndex === index}
132132
key={index}
133+
translations={translations}
133134
/>
134135
))
135136
) : (

packages/material-renderers/src/complex/MaterialTableControl.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,10 @@ interface NonEmptyRowProps {
260260
enabled: boolean;
261261
cells?: JsonFormsCellRendererRegistryEntry[];
262262
path: string;
263+
translations: ArrayTranslations
263264
}
264265

265-
const NonEmptyRowComponent =
266+
const NonEmptyRowComponent =
266267
({
267268
childPath,
268269
schema,
@@ -275,7 +276,8 @@ const NonEmptyRowComponent =
275276
showSortButtons,
276277
enabled,
277278
cells,
278-
path
279+
path,
280+
translations
279281
}: NonEmptyRowProps & WithDeleteDialogSupport) => {
280282
const moveUp = useMemo(() => moveUpCreator(path, rowIndex),[moveUpCreator, path, rowIndex]);
281283
const moveDown = useMemo(() => moveDownCreator(path, rowIndex),[moveDownCreator, path, rowIndex]);
@@ -295,13 +297,13 @@ const NonEmptyRowComponent =
295297
{showSortButtons ? (
296298
<Fragment>
297299
<Grid item>
298-
<IconButton aria-label={`Move up`} onClick={moveUp} disabled={!enableUp} size='large'>
300+
<IconButton aria-label={translations.upAriaLabel} onClick={moveUp} disabled={!enableUp} size='large'>
299301
<ArrowUpward />
300302
</IconButton>
301303
</Grid>
302304
<Grid item>
303305
<IconButton
304-
aria-label={`Move down`}
306+
aria-label={translations.downAriaLabel}
305307
onClick={moveDown}
306308
disabled={!enableDown}
307309
size='large'>
@@ -312,7 +314,7 @@ const NonEmptyRowComponent =
312314
) : null}
313315
<Grid item>
314316
<IconButton
315-
aria-label={`Delete`}
317+
aria-label={translations.removeAriaLabel}
316318
onClick={() => openDeleteDialog(childPath, rowIndex)}
317319
size='large'>
318320
<DeleteIcon />
@@ -378,6 +380,7 @@ const TableRows = ({
378380
enabled={enabled}
379381
cells={cells}
380382
path={path}
383+
translations={translations}
381384
/>
382385
);
383386
})}

0 commit comments

Comments
 (0)