@firecms/collection_editor 3.1.0 → 3.2.0-canary.44dc65b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/index.es.js +6887 -3709
  2. package/dist/index.es.js.map +1 -1
  3. package/dist/index.umd.js +6885 -3707
  4. package/dist/index.umd.js.map +1 -1
  5. package/dist/locales/de.d.ts +118 -0
  6. package/dist/locales/en.d.ts +118 -0
  7. package/dist/locales/es.d.ts +118 -0
  8. package/dist/locales/fr.d.ts +118 -0
  9. package/dist/locales/hi.d.ts +118 -0
  10. package/dist/locales/it.d.ts +118 -0
  11. package/dist/locales/pt.d.ts +118 -0
  12. package/package.json +8 -8
  13. package/src/locales/de.ts +123 -0
  14. package/src/locales/en.ts +143 -0
  15. package/src/locales/es.ts +123 -0
  16. package/src/locales/fr.ts +123 -0
  17. package/src/locales/hi.ts +123 -0
  18. package/src/locales/it.ts +123 -0
  19. package/src/locales/pt.ts +123 -0
  20. package/src/ui/EditorCollectionAction.tsx +3 -3
  21. package/src/ui/EditorEntityAction.tsx +3 -2
  22. package/src/ui/NewCollectionButton.tsx +3 -1
  23. package/src/ui/NewCollectionCard.tsx +7 -4
  24. package/src/ui/PropertyAddColumnComponent.tsx +3 -2
  25. package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +11 -10
  26. package/src/ui/collection_editor/CollectionDetailsForm.tsx +26 -24
  27. package/src/ui/collection_editor/CollectionEditorDialog.tsx +42 -38
  28. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +19 -18
  29. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +12 -10
  30. package/src/ui/collection_editor/DisplaySettingsForm.tsx +19 -17
  31. package/src/ui/collection_editor/EntityActionsEditTab.tsx +11 -12
  32. package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +5 -6
  33. package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +5 -5
  34. package/src/ui/collection_editor/EnumForm.tsx +6 -2
  35. package/src/ui/collection_editor/ExtendSettingsForm.tsx +8 -7
  36. package/src/ui/collection_editor/GeneralSettingsForm.tsx +36 -38
  37. package/src/ui/collection_editor/GetCodeDialog.tsx +13 -12
  38. package/src/ui/collection_editor/KanbanConfigSection.tsx +11 -9
  39. package/src/ui/collection_editor/LayoutModeSwitch.tsx +7 -4
  40. package/src/ui/collection_editor/PropertyEditView.tsx +74 -65
  41. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +16 -19
  42. package/src/ui/collection_editor/ViewModeSwitch.tsx +8 -6
  43. package/src/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +6 -3
  44. package/src/ui/collection_editor/import/CollectionEditorImportMapping.tsx +5 -2
  45. package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +3 -1
  46. package/src/ui/collection_editor/properties/CommonPropertyFields.tsx +6 -4
  47. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +20 -18
  48. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +5 -4
  49. package/src/ui/collection_editor/properties/MapPropertyField.tsx +8 -7
  50. package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +22 -23
  51. package/src/ui/collection_editor/properties/NumberPropertyField.tsx +3 -1
  52. package/src/ui/collection_editor/properties/ReferencePropertyField.tsx +5 -4
  53. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +46 -51
  54. package/src/ui/collection_editor/properties/StringPropertyField.tsx +3 -1
  55. package/src/ui/collection_editor/properties/UrlPropertyField.tsx +12 -10
  56. package/src/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +7 -4
  57. package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +8 -3
  58. package/src/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +5 -2
  59. package/src/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +7 -5
  60. package/src/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +10 -7
  61. package/src/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +11 -9
  62. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +4 -1
  63. package/src/useCollectionEditorPlugin.tsx +22 -6
@@ -15,6 +15,7 @@ import {
15
15
  PropertyConfig,
16
16
  PropertyConfigBadge,
17
17
  PropertyConfigId,
18
+ useTranslation,
18
19
  } from "@firecms/core";
19
20
  import {
20
21
  Button,
@@ -127,6 +128,8 @@ export const PropertyForm = React.memo(
127
128
  name: ""
128
129
  } as PropertyWithId;
129
130
 
131
+ const { t } = useTranslation();
132
+
130
133
  const disabled = (Boolean(property && !editableProperty(property)) || !collectionEditable);
131
134
 
132
135
  const lastSubmittedProperty = useRef<OnPropertyChangedParams | undefined>(property ? {
@@ -176,18 +179,18 @@ export const PropertyForm = React.memo(
176
179
  const errors: Record<string, any> = {};
177
180
  if (includeIdAndName) {
178
181
  if (!values.name) {
179
- errors.name = "Required";
182
+ errors.name = t("required");
180
183
  } else {
181
- const nameError = validateName(values.name);
184
+ const nameError = validateName(values.name, t);
182
185
  if (nameError)
183
186
  errors.name = nameError;
184
187
  }
185
188
  if (!values.id) {
186
- errors.id = "Required";
189
+ errors.id = t("required");
187
190
  } else {
188
191
  // Exclude the current property key when editing to avoid false duplicate error
189
192
  const keysToCheck = existingPropertyKeys?.filter(key => key !== propertyKey);
190
- const idError = validateId(values.id, keysToCheck);
193
+ const idError = validateId(values.id, keysToCheck, t);
191
194
  if (idError)
192
195
  errors.id = idError;
193
196
  }
@@ -196,21 +199,21 @@ export const PropertyForm = React.memo(
196
199
  if (values.dataType === "string") {
197
200
  if (values.validation?.matches && !isValidRegExp(values.validation?.matches.toString())) {
198
201
  errors.validation = {
199
- matches: "Invalid regular expression"
202
+ matches: t("invalid_regular_expression")
200
203
  }
201
204
  }
202
205
  }
203
206
  if (values.dataType === "reference" && !values.path) {
204
- errors.path = "You must specify a target collection for the field";
207
+ errors.path = t("must_specify_target_collection");
205
208
  }
206
209
  if (values.propertyConfig === "repeat") {
207
210
  if (!(values as any).of) {
208
- errors.of = "You need to specify a repeat field";
211
+ errors.of = t("need_specify_repeat_field");
209
212
  }
210
213
  }
211
214
  if (values.propertyConfig === "block") {
212
215
  if (!(values as any).oneOf) {
213
- errors.oneOf = "You need to specify the properties of this block";
216
+ errors.oneOf = t("need_specify_block_properties");
214
217
  }
215
218
  }
216
219
 
@@ -238,7 +241,7 @@ export const PropertyForm = React.memo(
238
241
  for (const type of conditionTypes) {
239
242
  const rule = conditions[type];
240
243
  if (rule && isIncompleteRule(rule)) {
241
- conditionErrors[type] = "Incomplete condition - please select a field";
244
+ conditionErrors[type] = t("incomplete_condition");
242
245
  }
243
246
  }
244
247
 
@@ -247,7 +250,7 @@ export const PropertyForm = React.memo(
247
250
  const rule = conditions[enumType];
248
251
  if (rule && typeof rule === "object" && rule.if) {
249
252
  if (isIncompleteRule(rule)) {
250
- conditionErrors[enumType] = "Incomplete condition - please select a field";
253
+ conditionErrors[enumType] = t("incomplete_condition");
251
254
  }
252
255
  }
253
256
  }
@@ -313,6 +316,8 @@ export function PropertyFormDialog({
313
316
  onOkClicked?: () => void;
314
317
  onCancel?: () => void;
315
318
  }) {
319
+ const { t } = useTranslation();
320
+
316
321
  const formexRef = useRef<FormexController<PropertyWithId>>(undefined);
317
322
  const getController = (helpers: FormexController<PropertyWithId>) => {
318
323
  formexRef.current = helpers;
@@ -330,7 +335,7 @@ export function PropertyFormDialog({
330
335
  e.stopPropagation();
331
336
  formexRef.current?.handleSubmit(e)
332
337
  }}>
333
- <DialogTitle hidden>Property edit view</DialogTitle>
338
+ <DialogTitle hidden>{t("property_edit_view")}</DialogTitle>
334
339
  <DialogContent>
335
340
 
336
341
  <PropertyForm {...formProps}
@@ -407,6 +412,8 @@ function PropertyEditFormFields({
407
412
  collectionProperties?: Properties;
408
413
  } & FormexController<PropertyWithId>) {
409
414
 
415
+ const { t } = useTranslation();
416
+
410
417
  const [selectOpen, setSelectOpen] = useState(autoOpenTypeSelect);
411
418
  const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
412
419
  const [selectedFieldConfigId, setSelectedFieldConfigId] = useState<string | undefined>(values?.dataType ? getFieldId(values) : undefined);
@@ -582,7 +589,7 @@ function PropertyEditFormFields({
582
589
  {selectedWidgetError &&
583
590
  <Typography variant="caption"
584
591
  className={"ml-3.5"}
585
- color={"error"}>Required</Typography>}
592
+ color={"error"}>{t("required")}</Typography>}
586
593
 
587
594
  {/*<Typography variant="caption" className={"ml-3.5"}>Define your own custom properties and*/}
588
595
  {/* components</Typography>*/}
@@ -626,11 +633,9 @@ function PropertyEditFormFields({
626
633
  <ConfirmationDialog open={deleteDialogOpen}
627
634
  onAccept={() => onDelete(values?.id, propertyNamespace)}
628
635
  onCancel={() => setDeleteDialogOpen(false)}
629
- title={<div>Delete this property?</div>}
636
+ title={<div>{t("delete_this_property")}</div>}
630
637
  body={
631
- <div> This will <b>not delete any
632
- data</b>, only modify the
633
- collection.</div>
638
+ <div>{t("delete_property_warning")}</div>
634
639
  } />}
635
640
 
636
641
  </>
@@ -639,53 +644,53 @@ function PropertyEditFormFields({
639
644
 
640
645
  const idRegEx = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
641
646
 
642
- function validateId(value?: string, existingPropertyKeys?: string[]) {
647
+ function validateId(value: string | undefined, existingPropertyKeys: string[] | undefined, t: any) {
643
648
 
644
649
  let error;
645
650
  if (!value) {
646
- error = "You must specify an id for the field";
651
+ error = t("error_must_specify_id");
647
652
  }
648
653
  if (value && !value.match(idRegEx)) {
649
- error = "The id can only contain letters, numbers and underscores (_), and not start with a number";
654
+ error = t("error_id_format");
650
655
  }
651
656
  if (value && existingPropertyKeys && existingPropertyKeys.includes(value)) {
652
- error = "There is another field with this ID already";
657
+ error = t("error_id_already_exists");
653
658
  }
654
659
  return error;
655
660
  }
656
661
 
657
- function validateName(value: string) {
662
+ function validateName(value: string, t: any) {
658
663
  let error;
659
664
  if (!value) {
660
- error = "You must specify a title for the field";
665
+ error = t("error_must_specify_title");
661
666
  }
662
667
  return error;
663
668
  }
664
669
 
665
670
  const WIDGET_TYPE_MAP: Record<PropertyConfigId, string> = {
666
- text_field: "Text",
667
- multiline: "Text",
668
- markdown: "Text",
669
- url: "Text",
670
- email: "Text",
671
- switch: "Boolean",
672
- user_select: "Users",
673
- select: "Select",
674
- multi_select: "Select",
675
- number_input: "Number",
676
- number_select: "Select",
677
- multi_number_select: "Select",
678
- file_upload: "File",
679
- multi_file_upload: "File",
680
- reference: "Reference",
681
- reference_as_string: "Text",
682
- multi_references: "Reference",
683
- date_time: "Date",
684
- group: "Group",
685
- key_value: "Group",
686
- repeat: "Array",
687
- custom_array: "Array",
688
- block: "Group"
671
+ text_field: "widget_group_text",
672
+ multiline: "widget_group_text",
673
+ markdown: "widget_group_text",
674
+ url: "widget_group_text",
675
+ email: "widget_group_text",
676
+ switch: "widget_group_boolean",
677
+ user_select: "widget_group_users",
678
+ select: "widget_group_select",
679
+ multi_select: "widget_group_select",
680
+ number_input: "widget_group_number",
681
+ number_select: "widget_group_select",
682
+ multi_number_select: "widget_group_select",
683
+ file_upload: "widget_group_file",
684
+ multi_file_upload: "widget_group_file",
685
+ reference: "widget_group_reference",
686
+ reference_as_string: "widget_group_text",
687
+ multi_references: "widget_group_reference",
688
+ date_time: "widget_group_date",
689
+ group: "widget_group_group",
690
+ key_value: "widget_group_group",
691
+ repeat: "widget_group_array",
692
+ custom_array: "widget_group_array",
693
+ block: "widget_group_group"
689
694
  };
690
695
 
691
696
  function WidgetSelectView({
@@ -712,6 +717,8 @@ function WidgetSelectView({
712
717
  inArray?: boolean
713
718
  }) {
714
719
 
720
+ const { t } = useTranslation();
721
+
715
722
  const allSupportedFields = Object.entries(supportedFields).concat(Object.entries(propertyConfigs));
716
723
 
717
724
  const displayedWidgets = (inArray
@@ -734,27 +741,27 @@ function WidgetSelectView({
734
741
  const computedFieldConfig = baseFieldConfig && propertyConfig ? mergeDeep(baseFieldConfig, propertyConfig) : propertyConfig;
735
742
 
736
743
  const groups: string[] = [...new Set(Object.keys(displayedWidgets).map(key => {
737
- const group = WIDGET_TYPE_MAP[key as PropertyConfigId];
738
- if (group) {
739
- return group;
744
+ const groupKey = WIDGET_TYPE_MAP[key as PropertyConfigId];
745
+ if (groupKey) {
746
+ return t(groupKey as any);
740
747
  }
741
- return "Custom/Other"
748
+ return t("custom_or_other")
742
749
  }))];
743
750
 
744
751
  return <>
745
- <div
746
- onClick={() => {
747
- if (!disabled) {
748
- onOpenChange(!open, Boolean(value));
749
- }
750
- }}
751
- className={cls(
752
- "select-none rounded-md text-sm p-4",
753
- fieldBackgroundMixin,
754
- disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
755
- "relative flex items-center",
756
- )}>
757
- {!value && <em>Select a property widget</em>}
752
+ <div
753
+ onClick={() => {
754
+ if (!disabled) {
755
+ onOpenChange(!open, Boolean(value));
756
+ }
757
+ }}
758
+ className={cls(
759
+ "select-none rounded-md text-sm p-4",
760
+ fieldBackgroundMixin,
761
+ disabled ? fieldBackgroundDisabledMixin : fieldBackgroundHoverMixin,
762
+ "relative flex items-center",
763
+ )}>
764
+ {!value && <em>{t("select_property_widget")}</em>}
758
765
  {value && computedFieldConfig && <div
759
766
  className={cls(
760
767
  "flex items-center")}>
@@ -774,7 +781,7 @@ function WidgetSelectView({
774
781
  onOpenChange={(open) => onOpenChange(open, Boolean(value))}
775
782
  maxWidth={"4xl"}>
776
783
  <DialogTitle>
777
- Select a property widget
784
+ {t("select_property_widget")}
778
785
  </DialogTitle>
779
786
  <DialogContent>
780
787
  <div>
@@ -784,7 +791,8 @@ function WidgetSelectView({
784
791
  <div className={"grid grid-cols-1 md:grid-cols-2 gap-x-4 gap-y-2 mt-4"}>
785
792
  {Object.entries(displayedWidgets).map(([key, propertyConfig]) => {
786
793
  const groupKey = WIDGET_TYPE_MAP[key as PropertyConfigId];
787
- if (groupKey === group) {
794
+ const translatedGroup = groupKey ? t(groupKey as any) : t("custom_or_other");
795
+ if (translatedGroup === group) {
788
796
  return <WidgetSelectViewItem
789
797
  key={key}
790
798
  initialProperty={initialProperty}
@@ -831,6 +839,7 @@ export function WidgetSelectViewItem({
831
839
  propertyConfig,
832
840
  existing
833
841
  }: PropertySelectItemProps) {
842
+ const { t } = useTranslation();
834
843
  const baseProperty = propertyConfig.property;
835
844
  const shouldWarnChangingDataType = existing && !isPropertyBuilder(baseProperty) && baseProperty.dataType !== initialProperty?.dataType;
836
845
 
@@ -847,7 +856,7 @@ export function WidgetSelectViewItem({
847
856
  <div>
848
857
  <div className={"flex flex-row gap-2 items-center"}>
849
858
  {shouldWarnChangingDataType && <Tooltip
850
- title={"This widget uses a different data type than the initially selected widget. This can cause errors with existing data."}>
859
+ title={t("error_changing_data_type")}>
851
860
  <WarningIcon size="smallest" className={"w-4"} />
852
861
  </Tooltip>}
853
862
  <Typography
@@ -5,7 +5,8 @@ import {
5
5
  EntityCustomView,
6
6
  resolveEntityView,
7
7
  useCustomizationController,
8
- User
8
+ User,
9
+ useTranslation
9
10
  } from "@firecms/core";
10
11
  import {
11
12
  AddIcon,
@@ -48,6 +49,7 @@ export function SubcollectionsEditTab({
48
49
  }) {
49
50
 
50
51
  const { entityViews: contextEntityViews } = useCustomizationController();
52
+ const { t } = useTranslation();
51
53
 
52
54
  const [subcollectionToDelete, setSubcollectionToDelete] = React.useState<string | undefined>();
53
55
  const [addEntityViewDialogOpen, setAddEntityViewDialogOpen] = React.useState<boolean>(false);
@@ -75,7 +77,7 @@ export function SubcollectionsEditTab({
75
77
 
76
78
  <div className={"flex-grow flex flex-col gap-4 items-start"}>
77
79
  <Typography variant={"h6"}>
78
- Subcollections of {values.name}
80
+ {t("subcollections_of")} {values.name}
79
81
  </Typography>
80
82
 
81
83
  <Paper className={"flex flex-col gap-4 p-2 w-full"}>
@@ -95,7 +97,7 @@ export function SubcollectionsEditTab({
95
97
  </TableCell>
96
98
  <TableCell
97
99
  align="right">
98
- <Tooltip title={"Remove"}
100
+ <Tooltip title={t("remove")}
99
101
  asChild={true}>
100
102
  <IconButton size="small"
101
103
  onClick={(e) => {
@@ -120,7 +122,7 @@ export function SubcollectionsEditTab({
120
122
  });
121
123
  }}
122
124
  startIcon={<AddIcon />}>
123
- Add subcollection
125
+ {t("add_subcollection")}
124
126
  </Button>
125
127
 
126
128
  </Paper>
@@ -129,7 +131,7 @@ export function SubcollectionsEditTab({
129
131
 
130
132
  <div className={"flex-grow flex flex-col gap-4 items-start"}>
131
133
  <Typography variant={"h6"}>
132
- Custom views
134
+ {t("custom_views")}
133
135
  </Typography>
134
136
 
135
137
  {totalEntityViews === 0 &&
@@ -138,8 +140,8 @@ export function SubcollectionsEditTab({
138
140
  href={"https://firecms.co/docs/cloud/quickstart"}
139
141
  component={"a"}
140
142
  rel="noopener noreferrer"
141
- target="_blank">More info</Button>}>
142
- Define your own custom views by uploading them with the CLI.
143
+ target="_blank">{t("more_info")}</Button>}>
144
+ {t("define_custom_views_cli")}
143
145
  </Alert>
144
146
  }
145
147
 
@@ -157,7 +159,7 @@ export function SubcollectionsEditTab({
157
159
  </TableCell>
158
160
  <TableCell
159
161
  align="right">
160
- <Tooltip title={"Remove"}
162
+ <Tooltip title={t("remove")}
161
163
  asChild={true}>
162
164
  <IconButton size="small"
163
165
  onClick={(e) => {
@@ -180,8 +182,7 @@ export function SubcollectionsEditTab({
180
182
  {view.name}
181
183
  </Typography>
182
184
  <Typography variant={"caption"} className={"flex-grow"}>
183
- This view is defined in code with
184
- key <code>{view.key}</code>
185
+ {t("view_defined_in_code")} <code>{view.key}</code>
185
186
  </Typography>
186
187
  </TableCell>
187
188
  </TableRow>
@@ -194,7 +195,7 @@ export function SubcollectionsEditTab({
194
195
  setAddEntityViewDialogOpen(true);
195
196
  }}
196
197
  startIcon={<AddIcon />}>
197
- Add custom entity view
198
+ {t("add_custom_entity_view")}
198
199
  </Button>
199
200
  </Paper>
200
201
 
@@ -233,10 +234,8 @@ export function SubcollectionsEditTab({
233
234
  });
234
235
  }}
235
236
  onCancel={() => setSubcollectionToDelete(undefined)}
236
- title={<>Delete this subcollection?</>}
237
- body={<> This will <b>not
238
- delete any data</b>, only
239
- the collection in the CMS</>} />}
237
+ title={<>{t("delete_this_subcollection")}</>}
238
+ body={<>{t("remove_collection_warning")}</>} />}
240
239
  {viewToDelete &&
241
240
  <ConfirmationDialog open={Boolean(viewToDelete)}
242
241
  onAccept={() => {
@@ -244,10 +243,8 @@ export function SubcollectionsEditTab({
244
243
  setViewToDelete(undefined);
245
244
  }}
246
245
  onCancel={() => setViewToDelete(undefined)}
247
- title={<>Remove this view?</>}
248
- body={<>This will <b>not
249
- delete any data</b>, only
250
- the view in the CMS</>} />}
246
+ title={<>{t("remove_this_view")}</>}
247
+ body={<>{t("remove_view_warning")}</>} />}
251
248
 
252
249
  <CollectionEditorDialog
253
250
  open={Boolean(currentDialog)}
@@ -1,4 +1,4 @@
1
- import { ViewMode } from "@firecms/core";
1
+ import { ViewMode, useTranslation } from "@firecms/core";
2
2
  import { AppsIcon, cls, ListIcon, ToggleButtonGroup, Typography, ViewKanbanIcon } from "@firecms/ui";
3
3
 
4
4
  export function ViewModeSwitch({
@@ -11,8 +11,10 @@ export function ViewModeSwitch({
11
11
  className?: string;
12
12
  }) {
13
13
 
14
+ const { t } = useTranslation();
15
+
14
16
  return <div className={cls(className)}>
15
- <Typography variant={"label"} color={"secondary"} className={"ml-3.5"}>Default collection view</Typography>
17
+ <Typography variant={"label"} color={"secondary"} className={"ml-3.5"}>{t("default_collection_view")}</Typography>
16
18
  <div className={"my-2"}>
17
19
  <ToggleButtonGroup
18
20
  value={value}
@@ -20,22 +22,22 @@ export function ViewModeSwitch({
20
22
  options={[
21
23
  {
22
24
  value: "table",
23
- label: "Table",
25
+ label: t("table_view"),
24
26
  icon: <ListIcon />
25
27
  },
26
28
  {
27
29
  value: "cards",
28
- label: "Cards",
30
+ label: t("cards_view"),
29
31
  icon: <AppsIcon />
30
32
  },
31
33
  {
32
34
  value: "kanban",
33
- label: "Kanban",
35
+ label: t("kanban_view"),
34
36
  icon: <ViewKanbanIcon />
35
37
  }
36
38
  ]}
37
39
  />
38
40
  </div>
39
- <Typography variant={"caption"} color={"secondary"} className={"ml-3.5"}>Choose how entities should be displayed by default</Typography>
41
+ <Typography variant={"caption"} color={"secondary"} className={"ml-3.5"}>{t("choose_how_entities_displayed_default")}</Typography>
40
42
  </div>
41
43
  }
@@ -5,7 +5,8 @@ import {
5
5
  Properties,
6
6
  useAuthController,
7
7
  useNavigationController,
8
- useSelectionController
8
+ useSelectionController,
9
+ useTranslation
9
10
  } from "@firecms/core";
10
11
  import { useEffect, useState } from "react";
11
12
  import { Typography } from "@firecms/ui";
@@ -19,6 +20,8 @@ export function CollectionEditorImportDataPreview({
19
20
  properties: Properties,
20
21
  propertiesOrder: string[]
21
22
  }) {
23
+ const { t } = useTranslation();
24
+
22
25
 
23
26
  const authController = useAuthController();
24
27
  const navigation = useNavigationController();
@@ -46,8 +49,8 @@ export function CollectionEditorImportDataPreview({
46
49
 
47
50
  return <EntityCollectionTable
48
51
  title={<div>
49
- <Typography variant={"subtitle2"}>Imported data preview</Typography>
50
- <Typography variant={"caption"}>Entities with the same id will be overwritten</Typography>
52
+ <Typography variant={"subtitle2"}>{t("imported_data_preview")}</Typography>
53
+ <Typography variant={"caption"}>{t("entities_with_same_id_overwritten")}</Typography>
51
54
  </div>}
52
55
  tableController={{
53
56
  data: importConfig.entities,
@@ -6,7 +6,8 @@ import {
6
6
  } from "@firecms/data_import";
7
7
  import { getIn, useFormex } from "@firecms/formex";
8
8
 
9
- import { getFieldConfig, getFieldId, Properties, Property, PropertyConfig, PropertyConfigBadge, } from "@firecms/core";
9
+ import { getFieldConfig, getFieldId, Properties, Property, PropertyConfig, PropertyConfigBadge, useTranslation
10
+ } from "@firecms/core";
10
11
  import { cls, Container, Select, SelectItem, Tooltip, Typography } from "@firecms/ui";
11
12
  import React, { useState } from "react";
12
13
  import { OnPropertyChangedParams, PropertyFormDialog, PropertyWithId } from "../PropertyEditView";
@@ -26,6 +27,8 @@ export function CollectionEditorImportMapping({
26
27
  propertyConfigs: Record<string, PropertyConfig>,
27
28
  collectionEditable: boolean
28
29
  }) {
30
+ const { t } = useTranslation();
31
+
29
32
 
30
33
  // const {
31
34
  // values,
@@ -142,7 +145,7 @@ export function CollectionEditorImportMapping({
142
145
  <div className={"overflow-auto my-auto"}>
143
146
  <Container maxWidth={"6xl"} className={"flex flex-col gap-4 p-8 m-auto"}>
144
147
 
145
- <Typography variant="h6" className={"my-4 ml-3.5"}>Data property mapping</Typography>
148
+ <Typography variant="h6" className={"my-4 ml-3.5"}>{t("data_property_mapping")}</Typography>
146
149
 
147
150
  <DataNewPropertiesMapping importConfig={importConfig}
148
151
  destinationProperties={values.properties as Properties}
@@ -4,11 +4,13 @@ import { Field, FormexFieldProps, getIn, useFormex } from "@firecms/formex";
4
4
  import { GeneralPropertyValidation } from "./validation/GeneralPropertyValidation";
5
5
  import { ValidationPanel } from "./validation/ValidationPanel";
6
6
  import { SwitchControl } from "../SwitchControl";
7
+ import { useTranslation } from "@firecms/core";
7
8
 
8
9
  export function BooleanPropertyField({ disabled }: {
9
10
  disabled: boolean;
10
11
  }) {
11
12
  const { values } = useFormex();
13
+ const { t } = useTranslation();
12
14
  const defaultValue = getIn(values, "defaultValue");
13
15
 
14
16
  return (
@@ -28,7 +30,7 @@ export function BooleanPropertyField({ disabled }: {
28
30
  {({ field, form }: FormexFieldProps) => {
29
31
  return <SwitchControl
30
32
  size={"medium"}
31
- label={defaultValue === null || defaultValue === undefined ? "Default value not set" : ("Default value is " + defaultValue.toString())}
33
+ label={defaultValue === null || defaultValue === undefined ? t("default_value_not_set") : t("default_value_is", { value: defaultValue.toString() })}
32
34
  disabled={disabled}
33
35
  allowIndeterminate={true} field={field}
34
36
  form={form}/>
@@ -2,7 +2,7 @@ import { Field, getIn, useFormex } from "@firecms/formex";
2
2
  import { DebouncedTextField } from "@firecms/ui";
3
3
  import { PropertyWithId } from "../PropertyEditView";
4
4
  import React from "react";
5
- import { FieldCaption, prettifyIdentifier, toSnakeCase } from "@firecms/core";
5
+ import { FieldCaption, prettifyIdentifier, toSnakeCase, useTranslation } from "@firecms/core";
6
6
 
7
7
  type CommonPropertyFieldsProps = {
8
8
  showErrors: boolean,
@@ -30,6 +30,8 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
30
30
  validate
31
31
  } = useFormex<PropertyWithId>();
32
32
 
33
+ const { t } = useTranslation();
34
+
33
35
  const name = "name";
34
36
  const nameError = showErrors && getIn(errors, name);
35
37
 
@@ -58,7 +60,7 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
58
60
  setFieldTouched(name, true);
59
61
  }}
60
62
  style={{ fontSize: 20 }}
61
- placeholder={"Field name"}
63
+ placeholder={t("field_name")}
62
64
  required
63
65
  disabled={disabled}
64
66
  error={Boolean(nameError)}/>
@@ -72,7 +74,7 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
72
74
  <Field
73
75
  name={id}
74
76
  as={DebouncedTextField}
75
- label={"ID"}
77
+ label={t("id")}
76
78
  value={values[id]}
77
79
  onChange={(e: any) => {
78
80
  const newIdValue = e.target.value;
@@ -95,7 +97,7 @@ export const CommonPropertyFields = React.forwardRef<HTMLDivElement, CommonPrope
95
97
  <div>
96
98
  <Field name={description}
97
99
  as={DebouncedTextField}
98
- label={"Description"}
100
+ label={t("description")}
99
101
  disabled={disabled}
100
102
  error={Boolean(descriptionError)}/>
101
103
  <FieldCaption error={Boolean(descriptionError)}>