@open-mercato/ui 0.6.6-develop.6516.1.86a8538145 → 0.6.6-develop.6520.1.55df6df792

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.
@@ -15,6 +15,7 @@ import {
15
15
  SelectValue
16
16
  } from "../../primitives/select.js";
17
17
  import { CUSTOM_FIELD_KINDS } from "@open-mercato/shared/modules/entities/kinds";
18
+ import { useOptionalT } from "@open-mercato/shared/lib/i18n/context";
18
19
  import { FieldRegistry } from "../fields/registry.js";
19
20
  import { slugify } from "@open-mercato/shared/lib/slugify";
20
21
  import { useConfirmDialog } from "../confirm-dialog/index.js";
@@ -29,10 +30,6 @@ import {
29
30
  import {
30
31
  normalizeCustomFieldOptions
31
32
  } from "@open-mercato/shared/modules/entities/options";
32
- const DEFAULT_KIND_OPTIONS = CUSTOM_FIELD_KINDS.map((k) => ({
33
- value: k,
34
- label: k.charAt(0).toUpperCase() + k.slice(1)
35
- }));
36
33
  const DEFAULT_VALUE_NONE = "__open_mercato_no_default__";
37
34
  function getDefaultValueNoneOptionValue(options) {
38
35
  const optionValues = new Set(options.map((option) => String(option.value)));
@@ -110,10 +107,10 @@ function FieldDefinitionsEditor({
110
107
  definitions,
111
108
  errors,
112
109
  deletedKeys,
113
- kindOptions = DEFAULT_KIND_OPTIONS,
110
+ kindOptions,
114
111
  orderNotice,
115
- infoNote = /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground mt-2", children: "Supported kinds: text, multiline, integer, float, boolean, select (with options/optionsUrl), currency (fixed currencies list), relation (with related entity and options URL)." }),
116
- addButtonLabel = "Add Field",
112
+ infoNote,
113
+ addButtonLabel,
117
114
  fieldsets = [],
118
115
  activeFieldset = null,
119
116
  onActiveFieldsetChange,
@@ -135,7 +132,27 @@ function FieldDefinitionsEditor({
135
132
  const { confirm, ConfirmDialogElement } = useConfirmDialog();
136
133
  const dragIndex = React.useRef(null);
137
134
  const hasFieldsets = fieldsets.length > 0;
138
- const t = React.useCallback((key, fallback) => translate ? translate(key, fallback) : fallback, [translate]);
135
+ const contextT = useOptionalT();
136
+ const t = React.useCallback(
137
+ (key, fallback) => {
138
+ if (translate) return translate(key, fallback);
139
+ if (contextT) return contextT(key, fallback);
140
+ return fallback;
141
+ },
142
+ [translate, contextT]
143
+ );
144
+ const resolvedKindOptions = React.useMemo(
145
+ () => kindOptions ?? CUSTOM_FIELD_KINDS.map((kind) => ({
146
+ value: kind,
147
+ label: t(`entities.customFields.editor.kindOption.${kind}`, kind.charAt(0).toUpperCase() + kind.slice(1))
148
+ })),
149
+ [kindOptions, t]
150
+ );
151
+ const resolvedInfoNote = infoNote !== void 0 ? infoNote : /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground mt-2", children: t(
152
+ "entities.customFields.editor.supportedKindsNote",
153
+ "Supported kinds: text, multiline, integer, float, boolean, select (with options/optionsUrl), currency (fixed currencies list), relation (with related entity and options URL)."
154
+ ) });
155
+ const resolvedAddButtonLabel = addButtonLabel ?? t("entities.customFields.editor.addField", "Add Field");
139
156
  const resolvedActiveFieldset = React.useMemo(() => {
140
157
  if (!hasFieldsets) return activeFieldset ?? null;
141
158
  if (activeFieldset === null) return null;
@@ -174,7 +191,7 @@ function FieldDefinitionsEditor({
174
191
  const handleAddFieldset = () => {
175
192
  if (!onFieldsetsChange) return;
176
193
  const code = ensureUniqueFieldsetCode(`fieldset_${fieldsets.length + 1}`, fieldsets);
177
- const nextFieldsets = [...fieldsets, { code, label: "New fieldset", icon: "layers" }];
194
+ const nextFieldsets = [...fieldsets, { code, label: t("entities.customFields.editor.newFieldsetLabel", "New fieldset"), icon: "layers" }];
178
195
  onFieldsetsChange(nextFieldsets);
179
196
  onActiveFieldsetChange?.(code);
180
197
  };
@@ -182,8 +199,8 @@ function FieldDefinitionsEditor({
182
199
  if (!onFieldsetsChange) return;
183
200
  if (!resolvedActiveFieldset) return;
184
201
  const confirmed = await confirm({
185
- title: `Delete fieldset "${resolvedActiveFieldset}"?`,
186
- text: "This will move its fields to Unassigned.",
202
+ title: t("entities.customFields.editor.deleteFieldsetTitle", 'Delete fieldset "{code}"?').replace("{code}", resolvedActiveFieldset),
203
+ text: t("entities.customFields.editor.deleteFieldsetText", "This will move its fields to Unassigned."),
187
204
  variant: "destructive"
188
205
  });
189
206
  if (!confirmed) return;
@@ -242,14 +259,14 @@ function FieldDefinitionsEditor({
242
259
  children: [
243
260
  hasFieldsets ? /* @__PURE__ */ jsxs("div", { className: "rounded border bg-card p-3 space-y-3", children: [
244
261
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
245
- /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-muted-foreground", children: "Fieldset" }),
262
+ /* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-muted-foreground", children: t("entities.customFields.fieldsetSelectorLabel", "Fieldset") }),
246
263
  /* @__PURE__ */ jsxs(
247
264
  Select,
248
265
  {
249
266
  value: resolvedActiveFieldset || void 0,
250
267
  onValueChange: (value) => handleActiveFieldsetChange(value ?? ""),
251
268
  children: [
252
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-auto min-w-[10rem]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Unassigned fields" }) }),
269
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", className: "w-auto min-w-[10rem]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("entities.customFields.editor.unassignedFields", "Unassigned fields") }) }),
253
270
  /* @__PURE__ */ jsx(SelectContent, { children: fieldsets.map((fs) => /* @__PURE__ */ jsx(SelectItem, { value: fs.code, children: fs.label || fs.code }, fs.code)) })
254
271
  ]
255
272
  }
@@ -263,7 +280,8 @@ function FieldDefinitionsEditor({
263
280
  className: "text-xs",
264
281
  children: [
265
282
  /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
266
- " Add"
283
+ " ",
284
+ t("entities.customFields.editor.add", "Add")
267
285
  ]
268
286
  }
269
287
  ),
@@ -277,13 +295,14 @@ function FieldDefinitionsEditor({
277
295
  className: "text-xs",
278
296
  children: [
279
297
  /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" }),
280
- " Delete"
298
+ " ",
299
+ t("entities.customFields.editor.delete", "Delete")
281
300
  ]
282
301
  }
283
302
  )
284
303
  ] }),
285
304
  resolvedActiveFieldset && activeFieldsetConfig ? /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-4 gap-3", children: [
286
- /* @__PURE__ */ jsx(FormField, { label: "Code", children: /* @__PURE__ */ jsx(
305
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.code", "Code"), children: /* @__PURE__ */ jsx(
287
306
  Input,
288
307
  {
289
308
  size: "sm",
@@ -292,7 +311,7 @@ function FieldDefinitionsEditor({
292
311
  onChange: (event) => handleFieldsetCodeInput(activeFieldsetConfig.code, event.target.value)
293
312
  }
294
313
  ) }),
295
- /* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
314
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.label", "Label"), children: /* @__PURE__ */ jsx(
296
315
  Input,
297
316
  {
298
317
  size: "sm",
@@ -300,7 +319,7 @@ function FieldDefinitionsEditor({
300
319
  onChange: (event) => handleFieldsetPatch(activeFieldsetConfig.code, { label: event.target.value })
301
320
  }
302
321
  ) }),
303
- /* @__PURE__ */ jsx(FormField, { label: "Icon", children: /* @__PURE__ */ jsxs(
322
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.icon", "Icon"), children: /* @__PURE__ */ jsxs(
304
323
  Select,
305
324
  {
306
325
  value: activeFieldsetConfig.icon || void 0,
@@ -308,12 +327,12 @@ function FieldDefinitionsEditor({
308
327
  icon: value || void 0
309
328
  }),
310
329
  children: [
311
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Default" }) }),
312
- /* @__PURE__ */ jsx(SelectContent, { children: FIELDSET_ICON_OPTIONS.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
330
+ /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("entities.customFields.editor.defaultOption", "Default") }) }),
331
+ /* @__PURE__ */ jsx(SelectContent, { children: FIELDSET_ICON_OPTIONS.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: t(`entities.customFields.editor.iconOption.${option.value}`, option.label) }, option.value)) })
313
332
  ]
314
333
  }
315
334
  ) }),
316
- /* @__PURE__ */ jsx(FormField, { label: "Description", children: /* @__PURE__ */ jsx(
335
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.description", "Description"), children: /* @__PURE__ */ jsx(
317
336
  Input,
318
337
  {
319
338
  size: "sm",
@@ -330,15 +349,15 @@ function FieldDefinitionsEditor({
330
349
  disabled: !canToggleSingleFieldset,
331
350
  checked: singleFieldsetChecked,
332
351
  onCheckedChange: (checked) => onSingleFieldsetPerRecordChange?.(checked === true),
333
- label: "Single fieldset per entity",
352
+ label: t("entities.customFields.editor.singleFieldsetPerEntity", "Single fieldset per entity"),
334
353
  containerClassName: "text-xs",
335
354
  contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
336
355
  }
337
356
  ),
338
- !canToggleSingleFieldset ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "(add at least two fieldsets to toggle)" }) : null
357
+ !canToggleSingleFieldset ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t("entities.customFields.editor.singleFieldsetToggleHint", "(add at least two fieldsets to toggle)") }) : null
339
358
  ] })
340
359
  ] }) : /* @__PURE__ */ jsxs("div", { className: "rounded border border-dashed bg-muted/30 p-4 text-sm text-muted-foreground flex flex-col gap-3", children: [
341
- /* @__PURE__ */ jsx("div", { children: "No fieldsets defined yet. Fieldsets let you group custom fields for different variants of the same entity (e.g., Fashion vs. Sport products)." }),
360
+ /* @__PURE__ */ jsx("div", { children: t("entities.customFields.editor.noFieldsets", "No fieldsets defined yet. Fieldsets let you group custom fields for different variants of the same entity (e.g., Fashion vs. Sport products).") }),
342
361
  /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
343
362
  Button,
344
363
  {
@@ -347,12 +366,12 @@ function FieldDefinitionsEditor({
347
366
  onClick: handleAddFieldset,
348
367
  children: [
349
368
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
350
- "Add first fieldset"
369
+ t("entities.customFields.editor.addFirstFieldset", "Add first fieldset")
351
370
  ]
352
371
  }
353
372
  ) })
354
373
  ] }),
355
- orderNotice?.dirty && /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-sticky -mt-1 -mb-1", children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 text-xs px-2 py-1 rounded border border-status-warning-border bg-status-warning-bg text-status-warning-text shadow-sm", children: orderNotice?.saving ? "Saving order\u2026" : orderNotice?.message ?? "Reordered \u2014 saving soon" }) }),
374
+ orderNotice?.dirty && /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-sticky -mt-1 -mb-1", children: /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 text-xs px-2 py-1 rounded border border-status-warning-border bg-status-warning-bg text-status-warning-text shadow-sm", children: orderNotice?.saving ? t("entities.customFields.editor.savingOrder", "Saving order\u2026") : orderNotice?.message ?? t("entities.customFields.editor.reorderedSavingSoon", "Reordered \u2014 saving soon") }) }),
356
375
  filteredDefinitions.map(({ definition, index }) => {
357
376
  const assignedFieldset = typeof definition.configJson?.fieldset === "string" ? definition.configJson.fieldset : null;
358
377
  const groupOptions = assignedFieldset ? fieldsets.find((fs) => fs.code === assignedFieldset)?.groups ?? [] : availableGroups;
@@ -393,7 +412,7 @@ function FieldDefinitionsEditor({
393
412
  {
394
413
  definition,
395
414
  error: errors?.[index],
396
- kindOptions,
415
+ kindOptions: resolvedKindOptions,
397
416
  onChange: (next) => onDefinitionChange(index, next),
398
417
  onRemove: () => onRemoveField(index),
399
418
  allowFieldsetSelection: hasFieldsets,
@@ -420,13 +439,13 @@ function FieldDefinitionsEditor({
420
439
  children: [
421
440
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
422
441
  " ",
423
- addButtonLabel
442
+ resolvedAddButtonLabel
424
443
  ]
425
444
  }
426
445
  ),
427
- infoNote,
446
+ resolvedInfoNote,
428
447
  deletedKeys && deletedKeys.length > 0 && onRestoreField ? /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground mt-2", children: [
429
- "Restore deleted fields:",
448
+ t("entities.customFields.editor.restoreDeletedFields", "Restore deleted fields:"),
430
449
  " ",
431
450
  deletedKeys.map((key, idx) => /* @__PURE__ */ jsxs("span", { children: [
432
451
  /* @__PURE__ */ jsx(
@@ -584,7 +603,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
584
603
  if (!currentFieldsetValue) return;
585
604
  const code = slugifyFieldsetCode(groupDraft.code || "");
586
605
  if (!code) {
587
- setGroupError("Group code is required.");
606
+ setGroupError(t("entities.customFields.editor.groupCodeRequired", "Group code is required."));
588
607
  return;
589
608
  }
590
609
  const group = {
@@ -634,7 +653,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
634
653
  const value = optionValueDraft.trim();
635
654
  const label = optionLabelDraft.trim();
636
655
  if (!value) {
637
- setOptionFormError("Value is required");
656
+ setOptionFormError(t("entities.customFields.editor.valueRequired", "Value is required"));
638
657
  return;
639
658
  }
640
659
  setOptionFormError(null);
@@ -653,7 +672,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
653
672
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
654
673
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
655
674
  /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center h-5 w-5 rounded hover:bg-muted cursor-grab active:cursor-grabbing", children: /* @__PURE__ */ jsx(GripVertical, { className: "h-4 w-4 opacity-70" }) }),
656
- "Drag to reorder"
675
+ t("entities.customFields.editor.dragToReorder", "Drag to reorder")
657
676
  ] }),
658
677
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
659
678
  /* @__PURE__ */ jsx(
@@ -664,17 +683,17 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
664
683
  onCheckedChange: (checked) => {
665
684
  apply({ isActive: checked === true }, true);
666
685
  },
667
- label: "Active",
686
+ label: t("entities.customFields.editor.active", "Active"),
668
687
  containerClassName: "text-sm",
669
688
  contentClassName: "gap-1 [&_label]:text-sm [&_label]:font-normal"
670
689
  }
671
690
  ),
672
- onTranslate && /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onTranslate, "aria-label": "Translate field", children: /* @__PURE__ */ jsx(Languages, { className: "h-4 w-4" }) }),
673
- /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onRemove, "aria-label": "Remove field", children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" }) })
691
+ onTranslate && /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onTranslate, "aria-label": t("entities.customFields.editor.translateField", "Translate field"), children: /* @__PURE__ */ jsx(Languages, { className: "h-4 w-4" }) }),
692
+ /* @__PURE__ */ jsx(IconButton, { variant: "outline", size: "sm", onClick: onRemove, "aria-label": t("entities.customFields.editor.removeField", "Remove field"), children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" }) })
674
693
  ] })
675
694
  ] }),
676
695
  /* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-1 md:grid-cols-12 gap-3 items-center", children: [
677
- /* @__PURE__ */ jsx(FormField, { label: "Key", error: error?.key, className: "md:col-span-6", children: /* @__PURE__ */ jsx(
696
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.key", "Key"), error: error?.key, className: "md:col-span-6", children: /* @__PURE__ */ jsx(
678
697
  Input,
679
698
  {
680
699
  inputClassName: "font-mono",
@@ -684,7 +703,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
684
703
  onBlur: commit
685
704
  }
686
705
  ) }),
687
- /* @__PURE__ */ jsx(FormField, { label: "Kind", error: error?.kind, className: "md:col-span-6", children: /* @__PURE__ */ jsxs(
706
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.kind", "Kind"), error: error?.kind, className: "md:col-span-6", children: /* @__PURE__ */ jsxs(
688
707
  Select,
689
708
  {
690
709
  value: local.kind || void 0,
@@ -700,21 +719,21 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
700
719
  ] }),
701
720
  allowFieldsetSelection ? /* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-1 md:grid-cols-2 gap-3", children: [
702
721
  /* @__PURE__ */ jsxs("div", { children: [
703
- /* @__PURE__ */ jsx("label", { className: "text-xs", children: "Assign to fieldset" }),
722
+ /* @__PURE__ */ jsx("label", { className: "text-xs", children: t("entities.customFields.editor.assignToFieldset", "Assign to fieldset") }),
704
723
  /* @__PURE__ */ jsxs(
705
724
  Select,
706
725
  {
707
726
  value: currentFieldsetValue || void 0,
708
727
  onValueChange: (value) => handleFieldsetSelect(value ?? ""),
709
728
  children: [
710
- /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Unassigned" }) }),
729
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("entities.customFields.editor.unassigned", "Unassigned") }) }),
711
730
  /* @__PURE__ */ jsx(SelectContent, { children: (fieldsets || []).map((fs) => /* @__PURE__ */ jsx(SelectItem, { value: fs.code, children: fs.label || fs.code }, fs.code)) })
712
731
  ]
713
732
  }
714
733
  )
715
734
  ] }),
716
735
  currentFieldsetValue ? /* @__PURE__ */ jsxs("div", { children: [
717
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx("label", { className: "text-xs", children: "Group" }) }),
736
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx("label", { className: "text-xs", children: t("entities.customFields.editor.group", "Group") }) }),
718
737
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1", children: [
719
738
  /* @__PURE__ */ jsxs(
720
739
  Select,
@@ -722,7 +741,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
722
741
  value: currentGroup?.code || void 0,
723
742
  onValueChange: (value) => handleGroupSelect(value ?? ""),
724
743
  children: [
725
- /* @__PURE__ */ jsx(SelectTrigger, { className: "flex-1", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "No group" }) }),
744
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "flex-1", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("entities.customFields.editor.noGroup", "No group") }) }),
726
745
  /* @__PURE__ */ jsx(SelectContent, { children: groupOptions.map((group) => /* @__PURE__ */ jsx(SelectItem, { value: group.code, children: group.title || group.code }, group.code)) })
727
746
  ]
728
747
  }
@@ -733,7 +752,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
733
752
  variant: "outline",
734
753
  className: "text-muted-foreground",
735
754
  onClick: () => handleOpenGroupDialog(),
736
- "aria-label": "Create group",
755
+ "aria-label": t("entities.customFields.editor.createGroup", "Create group"),
737
756
  children: /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
738
757
  }
739
758
  ),
@@ -743,7 +762,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
743
762
  variant: "outline",
744
763
  className: "text-muted-foreground",
745
764
  onClick: () => handleOpenGroupDialog(),
746
- "aria-label": "Edit groups",
765
+ "aria-label": t("entities.customFields.editor.editGroups", "Edit groups"),
747
766
  children: /* @__PURE__ */ jsx(Cog, { className: "h-4 w-4" })
748
767
  }
749
768
  )
@@ -751,7 +770,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
751
770
  ] }) : null
752
771
  ] }) : null,
753
772
  /* @__PURE__ */ jsxs("div", { className: "mt-3 grid grid-cols-1 md:grid-cols-2 gap-3", children: [
754
- /* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
773
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.label", "Label"), children: /* @__PURE__ */ jsx(
755
774
  Input,
756
775
  {
757
776
  value: typeof local.configJson?.label === "string" ? local.configJson.label : "",
@@ -759,7 +778,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
759
778
  onBlur: commit
760
779
  }
761
780
  ) }),
762
- /* @__PURE__ */ jsx(FormField, { label: "Description", children: /* @__PURE__ */ jsx(
781
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.description", "Description"), children: /* @__PURE__ */ jsx(
763
782
  Input,
764
783
  {
765
784
  value: typeof local.configJson?.description === "string" ? local.configJson.description : "",
@@ -769,7 +788,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
769
788
  ) }),
770
789
  (local.kind === "text" || local.kind === "multiline") && /* @__PURE__ */ jsxs(Fragment, { children: [
771
790
  /* @__PURE__ */ jsxs("div", { children: [
772
- /* @__PURE__ */ jsx("label", { className: "text-xs", children: "Editor" }),
791
+ /* @__PURE__ */ jsx("label", { className: "text-xs", children: t("entities.customFields.editor.editor", "Editor") }),
773
792
  /* @__PURE__ */ jsxs(
774
793
  Select,
775
794
  {
@@ -778,11 +797,11 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
778
797
  apply({ configJson: { ...local.configJson || {}, editor: value || void 0 } }, true);
779
798
  },
780
799
  children: [
781
- /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Default" }) }),
800
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: t("entities.customFields.editor.defaultOption", "Default") }) }),
782
801
  /* @__PURE__ */ jsxs(SelectContent, { children: [
783
- /* @__PURE__ */ jsx(SelectItem, { value: "markdown", children: "Markdown (UIW)" }),
784
- /* @__PURE__ */ jsx(SelectItem, { value: "simpleMarkdown", children: "Simple Markdown" }),
785
- /* @__PURE__ */ jsx(SelectItem, { value: "htmlRichText", children: "HTML Rich Text" })
802
+ /* @__PURE__ */ jsx(SelectItem, { value: "markdown", children: t("entities.customFields.editor.editorMarkdown", "Markdown (UIW)") }),
803
+ /* @__PURE__ */ jsx(SelectItem, { value: "simpleMarkdown", children: t("entities.customFields.editor.editorSimpleMarkdown", "Simple Markdown") }),
804
+ /* @__PURE__ */ jsx(SelectItem, { value: "htmlRichText", children: t("entities.customFields.editor.editorHtmlRichText", "HTML Rich Text") })
786
805
  ] })
787
806
  ]
788
807
  }
@@ -797,13 +816,13 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
797
816
  onCheckedChange: (checked) => {
798
817
  apply({ configJson: { ...local.configJson || {}, multi: checked === true } }, true);
799
818
  },
800
- label: "Multiple",
819
+ label: t("entities.customFields.editor.multiple", "Multiple"),
801
820
  containerClassName: "md:col-span-2",
802
821
  contentClassName: "gap-1 [&_label]:text-xs [&_label]:font-normal"
803
822
  }
804
823
  ),
805
824
  !!local.configJson?.multi && /* @__PURE__ */ jsxs("div", { className: "md:col-span-2", children: [
806
- /* @__PURE__ */ jsx("label", { className: "text-xs", children: "Multi-select input style" }),
825
+ /* @__PURE__ */ jsx("label", { className: "text-xs", children: t("entities.customFields.editor.multiSelectInputStyle", "Multi-select input style") }),
807
826
  /* @__PURE__ */ jsxs(
808
827
  Select,
809
828
  {
@@ -817,8 +836,8 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
817
836
  children: [
818
837
  /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
819
838
  /* @__PURE__ */ jsxs(SelectContent, { children: [
820
- /* @__PURE__ */ jsx(SelectItem, { value: "default", children: "Default" }),
821
- /* @__PURE__ */ jsx(SelectItem, { value: "listbox", children: "Listbox (searchable)" })
839
+ /* @__PURE__ */ jsx(SelectItem, { value: "default", children: t("entities.customFields.editor.defaultOption", "Default") }),
840
+ /* @__PURE__ */ jsx(SelectItem, { value: "listbox", children: t("entities.customFields.editor.listboxSearchable", "Listbox (searchable)") })
822
841
  ] })
823
842
  ]
824
843
  }
@@ -827,7 +846,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
827
846
  ] })
828
847
  ] }),
829
848
  local.kind === "select" && /* @__PURE__ */ jsxs("div", { className: "md:col-span-6 space-y-3", children: [
830
- /* @__PURE__ */ jsx("label", { className: "text-xs", children: "Options" }),
849
+ /* @__PURE__ */ jsx("label", { className: "text-xs", children: t("entities.customFields.editor.options", "Options") }),
831
850
  /* @__PURE__ */ jsx("div", { className: "space-y-2", children: resolvedOptions.length > 0 ? resolvedOptions.map((option, idx) => /* @__PURE__ */ jsxs(
832
851
  "div",
833
852
  {
@@ -844,14 +863,14 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
844
863
  size: "xs",
845
864
  className: "text-destructive hover:text-destructive/80",
846
865
  onClick: () => handleRemoveOption(idx),
847
- "aria-label": "Remove option",
866
+ "aria-label": t("entities.customFields.editor.removeOption", "Remove option"),
848
867
  children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" })
849
868
  }
850
869
  )
851
870
  ]
852
871
  },
853
872
  `${option.value}-${idx}`
854
- )) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "No options defined." }) }),
873
+ )) : /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: t("entities.customFields.editor.noOptionsDefined", "No options defined.") }) }),
855
874
  /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs(
856
875
  Button,
857
876
  {
@@ -861,13 +880,13 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
861
880
  onClick: handleOpenOptionDialog,
862
881
  children: [
863
882
  /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
864
- "Add option"
883
+ t("entities.customFields.editor.addOption", "Add option")
865
884
  ]
866
885
  }
867
886
  ) })
868
887
  ] }),
869
888
  (local.kind === "select" || local.kind === "relation") && /* @__PURE__ */ jsxs(Fragment, { children: [
870
- /* @__PURE__ */ jsx(FormField, { label: "Options URL", children: /* @__PURE__ */ jsx(
889
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.optionsUrl", "Options URL"), children: /* @__PURE__ */ jsx(
871
890
  Input,
872
891
  {
873
892
  placeholder: "/api/...",
@@ -876,7 +895,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
876
895
  onBlur: commit
877
896
  }
878
897
  ) }),
879
- local.kind === "relation" && /* @__PURE__ */ jsx(FormField, { label: "Related Entity ID", children: /* @__PURE__ */ jsx(
898
+ local.kind === "relation" && /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.relatedEntityId", "Related Entity ID"), children: /* @__PURE__ */ jsx(
880
899
  Input,
881
900
  {
882
901
  inputClassName: "font-mono",
@@ -898,13 +917,13 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
898
917
  ) })
899
918
  ] }),
900
919
  local.kind === "currency" && /* @__PURE__ */ jsxs("div", { className: "md:col-span-2", children: [
901
- /* @__PURE__ */ jsx("label", { className: "text-xs", children: "Options source" }),
920
+ /* @__PURE__ */ jsx("label", { className: "text-xs", children: t("entities.customFields.editor.optionsSource", "Options source") }),
902
921
  /* @__PURE__ */ jsx("div", { className: "rounded border bg-muted px-2 py-1 text-xs text-muted-foreground", children: "/api/currencies/options" })
903
922
  ] }),
904
- (local.kind === "integer" || local.kind === "float") && /* @__PURE__ */ jsx(FormField, { label: "Units (optional)", className: "md:col-span-2", children: /* @__PURE__ */ jsx(
923
+ (local.kind === "integer" || local.kind === "float") && /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.unitsOptional", "Units (optional)"), className: "md:col-span-2", children: /* @__PURE__ */ jsx(
905
924
  Input,
906
925
  {
907
- placeholder: "kg, cm, etc.",
926
+ placeholder: t("entities.customFields.editor.unitsPlaceholder", "kg, cm, etc."),
908
927
  value: typeof local.configJson?.unit === "string" ? local.configJson.unit : "",
909
928
  onChange: (event) => apply({ configJson: { ...local.configJson || {}, unit: event.target.value } }),
910
929
  onBlur: commit
@@ -913,7 +932,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
913
932
  ] }),
914
933
  /* @__PURE__ */ jsxs("div", { className: "mt-3 pt-3 border-t", children: [
915
934
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
916
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Validation rules" }),
935
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: t("entities.customFields.editor.validationRules", "Validation rules") }),
917
936
  /* @__PURE__ */ jsxs(
918
937
  Button,
919
938
  {
@@ -923,13 +942,13 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
923
942
  onClick: () => {
924
943
  apply((current) => {
925
944
  const list = Array.isArray(current.configJson?.validation) ? [...current.configJson.validation] : [];
926
- list.push({ rule: "required", message: "This field is required" });
945
+ list.push({ rule: "required", message: t("entities.customFields.editor.ruleRequiredMessage", "This field is required") });
927
946
  return { configJson: { ...current.configJson || {}, validation: list } };
928
947
  }, true);
929
948
  },
930
949
  children: [
931
950
  /* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }),
932
- "Add rule"
951
+ t("entities.customFields.editor.addRule", "Add rule")
933
952
  ]
934
953
  }
935
954
  )
@@ -970,7 +989,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
970
989
  /* @__PURE__ */ jsx("div", { className: "md:col-span-4", children: /* @__PURE__ */ jsx(
971
990
  Input,
972
991
  {
973
- placeholder: rule?.rule === "regex" ? "Pattern (e.g. ^[a-z]+$)" : ["lt", "lte", "gt", "gte"].includes(rule?.rule) ? "Number" : "\u2014",
992
+ placeholder: rule?.rule === "regex" ? t("entities.customFields.editor.rulePatternPlaceholder", "Pattern (e.g. ^[a-z]+$)") : ["lt", "lte", "gt", "gte"].includes(rule?.rule) ? t("entities.customFields.editor.ruleNumberPlaceholder", "Number") : "\u2014",
974
993
  value: rule?.param ?? "",
975
994
  onChange: (event) => {
976
995
  const value = ["lt", "lte", "gt", "gte"].includes(rule?.rule) ? Number(event.target.value) : event.target.value;
@@ -988,7 +1007,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
988
1007
  /* @__PURE__ */ jsx("div", { className: "md:col-span-4", children: /* @__PURE__ */ jsx(
989
1008
  Input,
990
1009
  {
991
- placeholder: "Error message",
1010
+ placeholder: t("entities.customFields.editor.ruleErrorMessagePlaceholder", "Error message"),
992
1011
  value: rule?.message || "",
993
1012
  onChange: (event) => {
994
1013
  const message = event.target.value;
@@ -1007,7 +1026,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1007
1026
  {
1008
1027
  variant: "outline",
1009
1028
  size: "sm",
1010
- "aria-label": "Remove rule",
1029
+ "aria-label": t("entities.customFields.editor.removeRule", "Remove rule"),
1011
1030
  onClick: () => {
1012
1031
  apply((current) => {
1013
1032
  const list = Array.isArray(current.configJson?.validation) ? [...current.configJson.validation] : [];
@@ -1019,7 +1038,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1019
1038
  }
1020
1039
  ) })
1021
1040
  ] }, index)),
1022
- (!Array.isArray(local.configJson?.validation) || local.configJson.validation.length === 0) && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "No validation rules defined." })
1041
+ (!Array.isArray(local.configJson?.validation) || local.configJson.validation.length === 0) && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: t("entities.customFields.editor.noValidationRules", "No validation rules defined.") })
1023
1042
  ] })
1024
1043
  ] }),
1025
1044
  /* @__PURE__ */ jsx("div", { className: "mt-3", children: (() => {
@@ -1182,11 +1201,11 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1182
1201
  },
1183
1202
  children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-sm", children: [
1184
1203
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
1185
- /* @__PURE__ */ jsx(DialogTitle, { children: "Add option" }),
1186
- /* @__PURE__ */ jsx(DialogDescription, { children: "Provide the stored value and optional label shown to users." })
1204
+ /* @__PURE__ */ jsx(DialogTitle, { children: t("entities.customFields.editor.addOption", "Add option") }),
1205
+ /* @__PURE__ */ jsx(DialogDescription, { children: t("entities.customFields.editor.addOptionDescription", "Provide the stored value and optional label shown to users.") })
1187
1206
  ] }),
1188
1207
  /* @__PURE__ */ jsxs("div", { className: "space-y-4 py-2", children: [
1189
- /* @__PURE__ */ jsx(FormField, { label: "Value", error: optionFormError ?? void 0, children: /* @__PURE__ */ jsx(
1208
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.value", "Value"), error: optionFormError ?? void 0, children: /* @__PURE__ */ jsx(
1190
1209
  Input,
1191
1210
  {
1192
1211
  inputClassName: "font-mono",
@@ -1198,18 +1217,18 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1198
1217
  }
1199
1218
  }
1200
1219
  ) }),
1201
- /* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
1220
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.label", "Label"), children: /* @__PURE__ */ jsx(
1202
1221
  Input,
1203
1222
  {
1204
- placeholder: "Label shown to users (optional)",
1223
+ placeholder: t("entities.customFields.editor.optionLabelPlaceholder", "Label shown to users (optional)"),
1205
1224
  value: optionLabelDraft,
1206
1225
  onChange: (event) => setOptionLabelDraft(event.target.value)
1207
1226
  }
1208
1227
  ) })
1209
1228
  ] }),
1210
1229
  /* @__PURE__ */ jsxs(DialogFooter, { children: [
1211
- /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: handleCloseOptionDialog, children: "Cancel" }),
1212
- /* @__PURE__ */ jsx(Button, { size: "sm", onClick: handleAddOption, children: "Add option" })
1230
+ /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: handleCloseOptionDialog, children: t("entities.customFields.editor.cancel", "Cancel") }),
1231
+ /* @__PURE__ */ jsx(Button, { size: "sm", onClick: handleAddOption, children: t("entities.customFields.editor.addOption", "Add option") })
1213
1232
  ] })
1214
1233
  ] })
1215
1234
  }
@@ -1228,11 +1247,11 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1228
1247
  },
1229
1248
  children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-md", children: [
1230
1249
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
1231
- /* @__PURE__ */ jsx(DialogTitle, { children: editingGroupCode ? "Edit group" : "New group" }),
1232
- /* @__PURE__ */ jsx(DialogDescription, { children: editingGroupCode ? "Update the selected group for this fieldset." : "Add a reusable group for this fieldset." })
1250
+ /* @__PURE__ */ jsx(DialogTitle, { children: editingGroupCode ? t("entities.customFields.editor.editGroup", "Edit group") : t("entities.customFields.editor.newGroup", "New group") }),
1251
+ /* @__PURE__ */ jsx(DialogDescription, { children: editingGroupCode ? t("entities.customFields.editor.editGroupDescription", "Update the selected group for this fieldset.") : t("entities.customFields.editor.newGroupDescription", "Add a reusable group for this fieldset.") })
1233
1252
  ] }),
1234
1253
  /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
1235
- /* @__PURE__ */ jsx(FormField, { label: "Group code", error: groupError ?? void 0, disabled: !!editingGroupCode, children: /* @__PURE__ */ jsx(
1254
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.groupCode", "Group code"), error: groupError ?? void 0, disabled: !!editingGroupCode, children: /* @__PURE__ */ jsx(
1236
1255
  Input,
1237
1256
  {
1238
1257
  inputClassName: "font-mono",
@@ -1242,27 +1261,27 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1242
1261
  if (groupError) setGroupError(null);
1243
1262
  },
1244
1263
  disabled: !!editingGroupCode,
1245
- placeholder: "e.g. buying_committee"
1264
+ placeholder: t("entities.customFields.editor.groupCodePlaceholder", "e.g. buying_committee")
1246
1265
  }
1247
1266
  ) }),
1248
- /* @__PURE__ */ jsx(FormField, { label: "Label", children: /* @__PURE__ */ jsx(
1267
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.label", "Label"), children: /* @__PURE__ */ jsx(
1249
1268
  Input,
1250
1269
  {
1251
1270
  value: groupDraft.title,
1252
1271
  onChange: (event) => setGroupDraft((prev) => ({ ...prev, title: event.target.value })),
1253
- placeholder: "Buying committee"
1272
+ placeholder: t("entities.customFields.editor.groupLabelPlaceholder", "Buying committee")
1254
1273
  }
1255
1274
  ) }),
1256
- /* @__PURE__ */ jsx(FormField, { label: "Hint", children: /* @__PURE__ */ jsx(
1275
+ /* @__PURE__ */ jsx(FormField, { label: t("entities.customFields.editor.hint", "Hint"), children: /* @__PURE__ */ jsx(
1257
1276
  Input,
1258
1277
  {
1259
1278
  value: groupDraft.hint,
1260
1279
  onChange: (event) => setGroupDraft((prev) => ({ ...prev, hint: event.target.value })),
1261
- placeholder: "Visible to merchandisers"
1280
+ placeholder: t("entities.customFields.editor.groupHintPlaceholder", "Visible to merchandisers")
1262
1281
  }
1263
1282
  ) }),
1264
1283
  currentFieldsetValue && groupOptions.length > 0 ? /* @__PURE__ */ jsxs("div", { children: [
1265
- /* @__PURE__ */ jsx("div", { className: "text-xs font-medium mb-1", children: "Existing groups" }),
1284
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-medium mb-1", children: t("entities.customFields.editor.existingGroups", "Existing groups") }),
1266
1285
  /* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-40 overflow-y-auto", children: groupOptions.map((group) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between rounded border px-3 py-2 text-sm", children: [
1267
1286
  /* @__PURE__ */ jsxs("div", { children: [
1268
1287
  /* @__PURE__ */ jsx("div", { className: "font-medium", children: group.title || group.code }),
@@ -1277,7 +1296,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1277
1296
  size: "xs",
1278
1297
  className: "text-muted-foreground hover:text-foreground",
1279
1298
  onClick: () => handleEditGroupEntry(group),
1280
- "aria-label": `Edit ${group.code}`,
1299
+ "aria-label": t("entities.customFields.editor.editGroupAria", "Edit {code}").replace("{code}", group.code),
1281
1300
  children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
1282
1301
  }
1283
1302
  ),
@@ -1288,7 +1307,7 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1288
1307
  size: "xs",
1289
1308
  className: "text-destructive hover:text-destructive/80",
1290
1309
  onClick: () => handleRemoveGroupEntry(group.code),
1291
- "aria-label": `Delete ${group.code}`,
1310
+ "aria-label": t("entities.customFields.editor.deleteGroupAria", "Delete {code}").replace("{code}", group.code),
1292
1311
  children: /* @__PURE__ */ jsx(Trash2, { className: "h-4 w-4" })
1293
1312
  }
1294
1313
  )
@@ -1297,8 +1316,8 @@ const FieldDefinitionCard = React.memo(function FieldDefinitionCard2({
1297
1316
  ] }) : null
1298
1317
  ] }),
1299
1318
  /* @__PURE__ */ jsxs(DialogFooter, { children: [
1300
- /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: () => setGroupDialogOpen(false), children: "Cancel" }),
1301
- /* @__PURE__ */ jsx(Button, { size: "sm", onClick: handleGroupDialogSubmit, children: "Save group" })
1319
+ /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: () => setGroupDialogOpen(false), children: t("entities.customFields.editor.cancel", "Cancel") }),
1320
+ /* @__PURE__ */ jsx(Button, { size: "sm", onClick: handleGroupDialogSubmit, children: t("entities.customFields.editor.saveGroup", "Save group") })
1302
1321
  ] })
1303
1322
  ] })
1304
1323
  }