@open-mercato/core 0.6.6-develop.6529.1.e1de4b3f27 → 0.6.6-develop.6531.1.87e9d31db6

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 (31) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/dictionaries/fields/dictionary.js +56 -41
  3. package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
  4. package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js +1 -0
  5. package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js.map +2 -2
  6. package/dist/modules/entities/backend/entities/user/[entityId]/page.js +49 -49
  7. package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
  8. package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js +1 -0
  9. package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js.map +2 -2
  10. package/dist/modules/sales/components/documents/AddressesSection.js +6 -2
  11. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  12. package/dist/modules/sales/components/documents/SalesDocumentForm.js +44 -0
  13. package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
  14. package/dist/modules/sales/components/documents/ShipmentDialog.js +59 -38
  15. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  16. package/package.json +7 -7
  17. package/src/modules/dictionaries/fields/dictionary.tsx +55 -32
  18. package/src/modules/dictionaries/i18n/de.json +2 -0
  19. package/src/modules/dictionaries/i18n/en.json +2 -0
  20. package/src/modules/dictionaries/i18n/es.json +2 -0
  21. package/src/modules/dictionaries/i18n/pl.json +2 -0
  22. package/src/modules/entities/backend/entities/system/[entityId]/page.meta.ts +1 -0
  23. package/src/modules/entities/backend/entities/user/[entityId]/page.meta.ts +1 -0
  24. package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +51 -49
  25. package/src/modules/entities/i18n/de.json +34 -0
  26. package/src/modules/entities/i18n/en.json +34 -0
  27. package/src/modules/entities/i18n/es.json +34 -0
  28. package/src/modules/entities/i18n/pl.json +34 -0
  29. package/src/modules/sales/components/documents/AddressesSection.tsx +6 -2
  30. package/src/modules/sales/components/documents/SalesDocumentForm.tsx +46 -0
  31. package/src/modules/sales/components/documents/ShipmentDialog.tsx +65 -40
@@ -1,4 +1,4 @@
1
- [build:core] found 3468 entry points
1
+ [build:core] found 3471 entry points
2
2
  [build:core] built successfully
3
3
  [build:core:generated] found 186 entry points
4
4
  [build:core:generated] built successfully
@@ -49,9 +49,12 @@ function DictionaryFieldDefEditor({ def, onChange }) {
49
49
  const [error, setError] = React.useState(null);
50
50
  const multiId = React.useId();
51
51
  const inlineCreateId = React.useId();
52
+ const inlineCreateHintId = React.useId();
53
+ const defaultValueHintId = React.useId();
52
54
  const selectedId = typeof def?.configJson?.dictionaryId === "string" ? def?.configJson?.dictionaryId : "";
53
55
  const inlineCreate = def?.configJson?.dictionaryInlineCreate !== false;
54
56
  const isMulti = def?.configJson?.multi === true;
57
+ const inlineCreateDisabled = !selectedId || isMulti;
55
58
  const errorLoadLabel = t("dictionaries.customFields.errorLoad", "Failed to load dictionaries.");
56
59
  React.useEffect(() => {
57
60
  let cancelled = false;
@@ -120,47 +123,56 @@ function DictionaryFieldDefEditor({ def, onChange }) {
120
123
  /* @__PURE__ */ jsx("span", { children: t("dictionaries.customFields.selectedHint", "Entries from this dictionary populate the field.") }),
121
124
  /* @__PURE__ */ jsx("a", { href: manageHref, className: "font-medium text-primary hover:underline", target: "_blank", rel: "noreferrer", children: t("dictionaries.customFields.manageLink", "Manage dictionaries") })
122
125
  ] }) : null,
123
- /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 text-xs", children: [
124
- /* @__PURE__ */ jsx(
125
- Checkbox,
126
- {
127
- id: multiId,
128
- checked: isMulti,
129
- onCheckedChange: (checked) => {
130
- const enabled = checked === true;
131
- onChange({ multi: enabled, defaultValue: enabled ? void 0 : def?.configJson?.defaultValue });
132
- },
133
- disabled: !selectedId
134
- }
135
- ),
136
- /* @__PURE__ */ jsx(
137
- "label",
138
- {
139
- htmlFor: multiId,
140
- className: selectedId ? "cursor-pointer select-none" : "cursor-not-allowed opacity-60",
141
- children: t("dictionaries.customFields.allowMultiple", "Allow selecting multiple entries")
142
- }
143
- )
126
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
127
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:gap-x-4", children: [
128
+ /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 text-xs", children: [
129
+ /* @__PURE__ */ jsx(
130
+ Checkbox,
131
+ {
132
+ id: multiId,
133
+ checked: isMulti,
134
+ onCheckedChange: (checked) => {
135
+ const enabled = checked === true;
136
+ onChange({ multi: enabled, defaultValue: enabled ? void 0 : def?.configJson?.defaultValue });
137
+ },
138
+ disabled: !selectedId
139
+ }
140
+ ),
141
+ /* @__PURE__ */ jsx(
142
+ "label",
143
+ {
144
+ htmlFor: multiId,
145
+ className: selectedId ? "cursor-pointer select-none" : "cursor-not-allowed opacity-60",
146
+ children: t("dictionaries.customFields.allowMultiple", "Allow selecting multiple entries")
147
+ }
148
+ )
149
+ ] }),
150
+ /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 text-xs", children: [
151
+ /* @__PURE__ */ jsx(
152
+ Checkbox,
153
+ {
154
+ id: inlineCreateId,
155
+ checked: !isMulti && inlineCreate,
156
+ onCheckedChange: (checked) => onChange({ dictionaryInlineCreate: checked === true }),
157
+ disabled: inlineCreateDisabled,
158
+ "aria-describedby": isMulti ? inlineCreateHintId : void 0
159
+ }
160
+ ),
161
+ /* @__PURE__ */ jsx(
162
+ "label",
163
+ {
164
+ htmlFor: inlineCreateId,
165
+ className: !inlineCreateDisabled ? "cursor-pointer select-none" : "cursor-not-allowed opacity-60",
166
+ children: t("dictionaries.customFields.allowInlineCreate", "Allow inline creation inside forms")
167
+ }
168
+ )
169
+ ] })
170
+ ] }),
171
+ isMulti ? /* @__PURE__ */ jsx("p", { id: inlineCreateHintId, className: "text-xs text-muted-foreground", children: t(
172
+ "dictionaries.customFields.inlineCreateSingleOnly",
173
+ "Inline creation is available for single-entry dictionary fields only."
174
+ ) }) : null
144
175
  ] }),
145
- !isMulti ? /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2 text-xs", children: [
146
- /* @__PURE__ */ jsx(
147
- Checkbox,
148
- {
149
- id: inlineCreateId,
150
- checked: inlineCreate,
151
- onCheckedChange: (checked) => onChange({ dictionaryInlineCreate: checked === true }),
152
- disabled: !selectedId
153
- }
154
- ),
155
- /* @__PURE__ */ jsx(
156
- "label",
157
- {
158
- htmlFor: inlineCreateId,
159
- className: selectedId ? "cursor-pointer select-none" : "cursor-not-allowed opacity-60",
160
- children: t("dictionaries.customFields.allowInlineCreate", "Allow inline creation inside forms")
161
- }
162
- )
163
- ] }) : null,
164
176
  selectedId && !isMulti ? /* @__PURE__ */ jsx(
165
177
  DictionaryDefaultSelector,
166
178
  {
@@ -168,7 +180,10 @@ function DictionaryFieldDefEditor({ def, onChange }) {
168
180
  defaultValue: typeof def?.configJson?.defaultValue === "string" ? def.configJson.defaultValue : "",
169
181
  onChange: (value) => onChange({ defaultValue: value || void 0 })
170
182
  }
171
- ) : null
183
+ ) : selectedId && isMulti ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 text-xs", children: /* @__PURE__ */ jsx("p", { id: defaultValueHintId, className: "text-xs text-muted-foreground", children: t(
184
+ "dictionaries.customFields.defaultValueMultiUnavailable",
185
+ "Default values are not available for multi-select dictionary fields."
186
+ ) }) }) : null
172
187
  ] });
173
188
  }
174
189
  function DictionaryFieldInput({ value, setValue, disabled, def }) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/dictionaries/fields/dictionary.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { FieldRegistry } from '@open-mercato/ui/backend/fields/registry'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { DictionarySelectControl } from '../components/DictionarySelectControl'\nimport { useDictionaryEntries } from '../components/hooks/useDictionaryEntries'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('dictionaries').child({ component: 'dictionary-field' })\n\ntype DictionaryFieldDefinition = {\n dictionaryId?: string\n dictionaryInlineCreate?: boolean\n multi?: boolean\n defaultValue?: string\n}\n\ntype Props = CrudCustomFieldRenderProps & { def?: DictionaryFieldDefinition }\n\ntype DictionarySummary = {\n id: string\n name: string\n key: string\n isActive: boolean\n}\n\nfunction DictionaryDefaultSelector({\n dictionaryId,\n defaultValue,\n onChange,\n}: {\n dictionaryId: string\n defaultValue: string\n onChange: (value: string) => void\n}) {\n const t = useT()\n const { data, isLoading } = useDictionaryEntries(dictionaryId)\n const entries = data?.entries ?? []\n const isStale = defaultValue && entries.length > 0 && !entries.some((e) => e.value === defaultValue)\n\n return (\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.defaultValue', 'Default value')}\n </label>\n <Select\n value={defaultValue ?? ''}\n onValueChange={(next) => onChange(next ?? '')}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.defaultValueNone', 'No default')} />\n </SelectTrigger>\n <SelectContent>\n {entries.map((entry) => (\n <SelectItem key={entry.value} value={entry.value}>\n {entry.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {isLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {isStale ? (\n <p className=\"text-xs text-status-warning-text\">\n {t('dictionaries.customFields.defaultValueStale', 'Default entry not found \u2014 it may have been deleted or renamed.')}\n </p>\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldDefEditor({ def, onChange }: { def: { configJson?: DictionaryFieldDefinition } | undefined; onChange: (patch: Partial<DictionaryFieldDefinition>) => void }) {\n const t = useT()\n const [items, setItems] = React.useState<DictionarySummary[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const multiId = React.useId()\n const inlineCreateId = React.useId()\n const selectedId = typeof def?.configJson?.dictionaryId === 'string' ? def?.configJson?.dictionaryId : ''\n const inlineCreate = def?.configJson?.dictionaryInlineCreate !== false\n const isMulti = def?.configJson?.multi === true\n const errorLoadLabel = t('dictionaries.customFields.errorLoad', 'Failed to load dictionaries.')\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n try {\n const call = await apiCall<{ items?: unknown[]; error?: string }>(\n '/api/dictionaries?includeInactive=true',\n )\n if (!call.ok) {\n const message =\n typeof call.result?.error === 'string' ? call.result.error : 'Failed to load dictionaries'\n throw new Error(message)\n }\n const entries = Array.isArray(call.result?.items) ? call.result!.items : []\n if (!cancelled) {\n setItems(\n entries.map((entry: any) => ({\n id: String(entry.id),\n name: typeof entry.name === 'string' && entry.name.trim().length ? entry.name : String(entry.key ?? entry.id),\n key: typeof entry.key === 'string' ? entry.key : '',\n isActive: entry.isActive !== false,\n })),\n )\n }\n } catch (err) {\n if (!cancelled) {\n logger.error('Failed to load dictionaries list', { err })\n setError(errorLoadLabel)\n }\n } finally {\n if (!cancelled) {\n setLoading(false)\n }\n }\n }\n load().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [errorLoadLabel])\n\n const manageHref = '/backend/config/dictionaries'\n\n return (\n <div className=\"mt-3 space-y-3 rounded border border-dashed border-muted-foreground/40 bg-muted/30 p-3\">\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.dictionaryLabel', 'Dictionary source')}\n </label>\n <Select\n value={selectedId ?? ''}\n onValueChange={(next) => onChange({ dictionaryId: next || undefined })}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.dictionaryPlaceholder', 'Select a dictionary')} />\n </SelectTrigger>\n <SelectContent>\n {items.map((item) => (\n <SelectItem key={item.id} value={item.id}>\n {item.name}\n {item.isActive ? '' : ` (${t('dictionaries.customFields.inactive', 'inactive')})`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {loading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {error ? <p className=\"text-xs text-status-error-text\">{error}</p> : null}\n {!loading && !error && items.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.empty', 'No dictionaries available yet. Create one first.')}\n </p>\n ) : null}\n </div>\n {selectedId ? (\n <div className=\"flex flex-wrap items-center justify-between gap-2 rounded bg-background/80 px-2 py-1 text-xs text-muted-foreground\">\n <span>{t('dictionaries.customFields.selectedHint', 'Entries from this dictionary populate the field.')}</span>\n <a href={manageHref} className=\"font-medium text-primary hover:underline\" target=\"_blank\" rel=\"noreferrer\">\n {t('dictionaries.customFields.manageLink', 'Manage dictionaries')}\n </a>\n </div>\n ) : null}\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={multiId}\n checked={isMulti}\n onCheckedChange={(checked) => {\n const enabled = checked === true\n onChange({ multi: enabled, defaultValue: enabled ? undefined : def?.configJson?.defaultValue })\n }}\n disabled={!selectedId}\n />\n <label\n htmlFor={multiId}\n className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowMultiple', 'Allow selecting multiple entries')}\n </label>\n </div>\n {!isMulti ? (\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={inlineCreateId}\n checked={inlineCreate}\n onCheckedChange={(checked) => onChange({ dictionaryInlineCreate: checked === true })}\n disabled={!selectedId}\n />\n <label\n htmlFor={inlineCreateId}\n className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowInlineCreate', 'Allow inline creation inside forms')}\n </label>\n </div>\n ) : null}\n {selectedId && !isMulti ? (\n <DictionaryDefaultSelector\n dictionaryId={selectedId}\n defaultValue={typeof def?.configJson?.defaultValue === 'string' ? def.configJson.defaultValue : ''}\n onChange={(value) => onChange({ defaultValue: value || undefined })}\n />\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldInput({ value, setValue, disabled, def }: Props) {\n const t = useT()\n const dictionaryId = def?.dictionaryId\n if (!dictionaryId) {\n return (\n <div className=\"rounded border border-dashed p-3 text-sm text-muted-foreground\">\n {t('dictionaries.config.entries.error.load', 'Failed to load dictionary entries.')}\n </div>\n )\n }\n const normalizedValue = typeof value === 'string' ? value : Array.isArray(value) ? String(value[0] ?? '') : undefined\n return (\n <DictionarySelectControl\n dictionaryId={dictionaryId}\n value={normalizedValue ?? ''}\n onChange={(next) => setValue(next ?? undefined)}\n allowInlineCreate={def?.dictionaryInlineCreate !== false}\n disabled={disabled}\n />\n )\n}\n\nFieldRegistry.register('dictionary', {\n input: DictionaryFieldInput,\n defEditor: (props) => <DictionaryFieldDefEditor {...props} />,\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { FieldRegistry } from '@open-mercato/ui/backend/fields/registry'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Checkbox } from '@open-mercato/ui/primitives/checkbox'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { DictionarySelectControl } from '../components/DictionarySelectControl'\nimport { useDictionaryEntries } from '../components/hooks/useDictionaryEntries'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('dictionaries').child({ component: 'dictionary-field' })\n\ntype DictionaryFieldDefinition = {\n dictionaryId?: string\n dictionaryInlineCreate?: boolean\n multi?: boolean\n defaultValue?: string\n}\n\ntype Props = CrudCustomFieldRenderProps & { def?: DictionaryFieldDefinition }\n\ntype DictionarySummary = {\n id: string\n name: string\n key: string\n isActive: boolean\n}\n\nfunction DictionaryDefaultSelector({\n dictionaryId,\n defaultValue,\n onChange,\n}: {\n dictionaryId: string\n defaultValue: string\n onChange: (value: string) => void\n}) {\n const t = useT()\n const { data, isLoading } = useDictionaryEntries(dictionaryId)\n const entries = data?.entries ?? []\n const isStale = defaultValue && entries.length > 0 && !entries.some((e) => e.value === defaultValue)\n\n return (\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.defaultValue', 'Default value')}\n </label>\n <Select\n value={defaultValue ?? ''}\n onValueChange={(next) => onChange(next ?? '')}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.defaultValueNone', 'No default')} />\n </SelectTrigger>\n <SelectContent>\n {entries.map((entry) => (\n <SelectItem key={entry.value} value={entry.value}>\n {entry.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {isLoading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {isStale ? (\n <p className=\"text-xs text-status-warning-text\">\n {t('dictionaries.customFields.defaultValueStale', 'Default entry not found \u2014 it may have been deleted or renamed.')}\n </p>\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldDefEditor({ def, onChange }: { def: { configJson?: DictionaryFieldDefinition } | undefined; onChange: (patch: Partial<DictionaryFieldDefinition>) => void }) {\n const t = useT()\n const [items, setItems] = React.useState<DictionarySummary[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n const multiId = React.useId()\n const inlineCreateId = React.useId()\n const inlineCreateHintId = React.useId()\n const defaultValueHintId = React.useId()\n const selectedId = typeof def?.configJson?.dictionaryId === 'string' ? def?.configJson?.dictionaryId : ''\n const inlineCreate = def?.configJson?.dictionaryInlineCreate !== false\n const isMulti = def?.configJson?.multi === true\n const inlineCreateDisabled = !selectedId || isMulti\n const errorLoadLabel = t('dictionaries.customFields.errorLoad', 'Failed to load dictionaries.')\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n try {\n const call = await apiCall<{ items?: unknown[]; error?: string }>(\n '/api/dictionaries?includeInactive=true',\n )\n if (!call.ok) {\n const message =\n typeof call.result?.error === 'string' ? call.result.error : 'Failed to load dictionaries'\n throw new Error(message)\n }\n const entries = Array.isArray(call.result?.items) ? call.result!.items : []\n if (!cancelled) {\n setItems(\n entries.map((entry: any) => ({\n id: String(entry.id),\n name: typeof entry.name === 'string' && entry.name.trim().length ? entry.name : String(entry.key ?? entry.id),\n key: typeof entry.key === 'string' ? entry.key : '',\n isActive: entry.isActive !== false,\n })),\n )\n }\n } catch (err) {\n if (!cancelled) {\n logger.error('Failed to load dictionaries list', { err })\n setError(errorLoadLabel)\n }\n } finally {\n if (!cancelled) {\n setLoading(false)\n }\n }\n }\n load().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [errorLoadLabel])\n\n const manageHref = '/backend/config/dictionaries'\n\n return (\n <div className=\"mt-3 space-y-3 rounded border border-dashed border-muted-foreground/40 bg-muted/30 p-3\">\n <div className=\"space-y-1\">\n <label className=\"text-xs font-medium text-muted-foreground\">\n {t('dictionaries.customFields.dictionaryLabel', 'Dictionary source')}\n </label>\n <Select\n value={selectedId ?? ''}\n onValueChange={(next) => onChange({ dictionaryId: next || undefined })}\n >\n <SelectTrigger size=\"sm\">\n <SelectValue placeholder={t('dictionaries.customFields.dictionaryPlaceholder', 'Select a dictionary')} />\n </SelectTrigger>\n <SelectContent>\n {items.map((item) => (\n <SelectItem key={item.id} value={item.id}>\n {item.name}\n {item.isActive ? '' : ` (${t('dictionaries.customFields.inactive', 'inactive')})`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {loading ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.loading', 'Loading dictionaries\u2026')}\n </p>\n ) : null}\n {error ? <p className=\"text-xs text-status-error-text\">{error}</p> : null}\n {!loading && !error && items.length === 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('dictionaries.customFields.empty', 'No dictionaries available yet. Create one first.')}\n </p>\n ) : null}\n </div>\n {selectedId ? (\n <div className=\"flex flex-wrap items-center justify-between gap-2 rounded bg-background/80 px-2 py-1 text-xs text-muted-foreground\">\n <span>{t('dictionaries.customFields.selectedHint', 'Entries from this dictionary populate the field.')}</span>\n <a href={manageHref} className=\"font-medium text-primary hover:underline\" target=\"_blank\" rel=\"noreferrer\">\n {t('dictionaries.customFields.manageLink', 'Manage dictionaries')}\n </a>\n </div>\n ) : null}\n <div className=\"space-y-2\">\n <div className=\"flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center sm:gap-x-4\">\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={multiId}\n checked={isMulti}\n onCheckedChange={(checked) => {\n const enabled = checked === true\n onChange({ multi: enabled, defaultValue: enabled ? undefined : def?.configJson?.defaultValue })\n }}\n disabled={!selectedId}\n />\n <label\n htmlFor={multiId}\n className={selectedId ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowMultiple', 'Allow selecting multiple entries')}\n </label>\n </div>\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <Checkbox\n id={inlineCreateId}\n checked={!isMulti && inlineCreate}\n onCheckedChange={(checked) => onChange({ dictionaryInlineCreate: checked === true })}\n disabled={inlineCreateDisabled}\n aria-describedby={isMulti ? inlineCreateHintId : undefined}\n />\n <label\n htmlFor={inlineCreateId}\n className={!inlineCreateDisabled ? 'cursor-pointer select-none' : 'cursor-not-allowed opacity-60'}\n >\n {t('dictionaries.customFields.allowInlineCreate', 'Allow inline creation inside forms')}\n </label>\n </div>\n </div>\n {isMulti ? (\n <p id={inlineCreateHintId} className=\"text-xs text-muted-foreground\">\n {t(\n 'dictionaries.customFields.inlineCreateSingleOnly',\n 'Inline creation is available for single-entry dictionary fields only.',\n )}\n </p>\n ) : null}\n </div>\n {selectedId && !isMulti ? (\n <DictionaryDefaultSelector\n dictionaryId={selectedId}\n defaultValue={typeof def?.configJson?.defaultValue === 'string' ? def.configJson.defaultValue : ''}\n onChange={(value) => onChange({ defaultValue: value || undefined })}\n />\n ) : selectedId && isMulti ? (\n <div className=\"inline-flex items-center gap-2 text-xs\">\n <p id={defaultValueHintId} className=\"text-xs text-muted-foreground\">\n {t(\n 'dictionaries.customFields.defaultValueMultiUnavailable',\n 'Default values are not available for multi-select dictionary fields.',\n )}\n </p>\n </div>\n ) : null}\n </div>\n )\n}\n\nfunction DictionaryFieldInput({ value, setValue, disabled, def }: Props) {\n const t = useT()\n const dictionaryId = def?.dictionaryId\n if (!dictionaryId) {\n return (\n <div className=\"rounded border border-dashed p-3 text-sm text-muted-foreground\">\n {t('dictionaries.config.entries.error.load', 'Failed to load dictionary entries.')}\n </div>\n )\n }\n const normalizedValue = typeof value === 'string' ? value : Array.isArray(value) ? String(value[0] ?? '') : undefined\n return (\n <DictionarySelectControl\n dictionaryId={dictionaryId}\n value={normalizedValue ?? ''}\n onChange={(next) => setValue(next ?? undefined)}\n allowInlineCreate={def?.dictionaryInlineCreate !== false}\n disabled={disabled}\n />\n )\n}\n\nFieldRegistry.register('dictionary', {\n input: DictionaryFieldInput,\n defEditor: (props) => <DictionaryFieldDefEditor {...props} />,\n})\n"],
5
+ "mappings": ";AAqDM,cAGA,YAHA;AAnDN,YAAY,WAAW;AAEvB,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,gBAAgB;AACzB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,+BAA+B;AACxC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,cAAc,EAAE,MAAM,EAAE,WAAW,mBAAmB,CAAC;AAkBnF,SAAS,0BAA0B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,IAAI,KAAK;AACf,QAAM,EAAE,MAAM,UAAU,IAAI,qBAAqB,YAAY;AAC7D,QAAM,UAAU,MAAM,WAAW,CAAC;AAClC,QAAM,UAAU,gBAAgB,QAAQ,SAAS,KAAK,CAAC,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,YAAY;AAEnG,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,wBAAC,WAAM,WAAU,6CACd,YAAE,0CAA0C,eAAe,GAC9D;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,gBAAgB;AAAA,QACvB,eAAe,CAAC,SAAS,SAAS,QAAQ,EAAE;AAAA,QAE5C;AAAA,8BAAC,iBAAc,MAAK,MAClB,8BAAC,eAAY,aAAa,EAAE,8CAA8C,YAAY,GAAG,GAC3F;AAAA,UACA,oBAAC,iBACE,kBAAQ,IAAI,CAAC,UACZ,oBAAC,cAA6B,OAAO,MAAM,OACxC,gBAAM,SADQ,MAAM,KAEvB,CACD,GACH;AAAA;AAAA;AAAA,IACF;AAAA,IACC,YACC,oBAAC,OAAE,WAAU,iCACV,YAAE,qCAAqC,4BAAuB,GACjE,IACE;AAAA,IACH,UACC,oBAAC,OAAE,WAAU,oCACV,YAAE,+CAA+C,qEAAgE,GACpH,IACE;AAAA,KACN;AAEJ;AAEA,SAAS,yBAAyB,EAAE,KAAK,SAAS,GAAmI;AACnL,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAA8B,CAAC,CAAC;AAChE,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAClD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAC5D,QAAM,UAAU,MAAM,MAAM;AAC5B,QAAM,iBAAiB,MAAM,MAAM;AACnC,QAAM,qBAAqB,MAAM,MAAM;AACvC,QAAM,qBAAqB,MAAM,MAAM;AACvC,QAAM,aAAa,OAAO,KAAK,YAAY,iBAAiB,WAAW,KAAK,YAAY,eAAe;AACvG,QAAM,eAAe,KAAK,YAAY,2BAA2B;AACjE,QAAM,UAAU,KAAK,YAAY,UAAU;AAC3C,QAAM,uBAAuB,CAAC,cAAc;AAC5C,QAAM,iBAAiB,EAAE,uCAAuC,8BAA8B;AAE9F,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,OAAO;AACpB,iBAAW,IAAI;AACf,eAAS,IAAI;AACb,UAAI;AACF,cAAM,OAAO,MAAM;AAAA,UACjB;AAAA,QACF;AACA,YAAI,CAAC,KAAK,IAAI;AACZ,gBAAM,UACJ,OAAO,KAAK,QAAQ,UAAU,WAAW,KAAK,OAAO,QAAQ;AAC/D,gBAAM,IAAI,MAAM,OAAO;AAAA,QACzB;AACA,cAAM,UAAU,MAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,KAAK,OAAQ,QAAQ,CAAC;AAC1E,YAAI,CAAC,WAAW;AACd;AAAA,YACE,QAAQ,IAAI,CAAC,WAAgB;AAAA,cAC3B,IAAI,OAAO,MAAM,EAAE;AAAA,cACnB,MAAM,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,KAAK,EAAE,SAAS,MAAM,OAAO,OAAO,MAAM,OAAO,MAAM,EAAE;AAAA,cAC5G,KAAK,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM;AAAA,cACjD,UAAU,MAAM,aAAa;AAAA,YAC/B,EAAE;AAAA,UACJ;AAAA,QACF;AAAA,MACF,SAAS,KAAK;AACZ,YAAI,CAAC,WAAW;AACd,iBAAO,MAAM,oCAAoC,EAAE,IAAI,CAAC;AACxD,mBAAS,cAAc;AAAA,QACzB;AAAA,MACF,UAAE;AACA,YAAI,CAAC,WAAW;AACd,qBAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACA,SAAK,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AACrB,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,aAAa;AAEnB,SACE,qBAAC,SAAI,WAAU,0FACb;AAAA,yBAAC,SAAI,WAAU,aACb;AAAA,0BAAC,WAAM,WAAU,6CACd,YAAE,6CAA6C,mBAAmB,GACrE;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,cAAc;AAAA,UACrB,eAAe,CAAC,SAAS,SAAS,EAAE,cAAc,QAAQ,OAAU,CAAC;AAAA,UAErE;AAAA,gCAAC,iBAAc,MAAK,MAClB,8BAAC,eAAY,aAAa,EAAE,mDAAmD,qBAAqB,GAAG,GACzG;AAAA,YACA,oBAAC,iBACE,gBAAM,IAAI,CAAC,SACV,qBAAC,cAAyB,OAAO,KAAK,IACnC;AAAA,mBAAK;AAAA,cACL,KAAK,WAAW,KAAK,KAAK,EAAE,sCAAsC,UAAU,CAAC;AAAA,iBAF/D,KAAK,EAGtB,CACD,GACH;AAAA;AAAA;AAAA,MACF;AAAA,MACC,UACC,oBAAC,OAAE,WAAU,iCACV,YAAE,qCAAqC,4BAAuB,GACjE,IACE;AAAA,MACH,QAAQ,oBAAC,OAAE,WAAU,kCAAkC,iBAAM,IAAO;AAAA,MACpE,CAAC,WAAW,CAAC,SAAS,MAAM,WAAW,IACtC,oBAAC,OAAE,WAAU,iCACV,YAAE,mCAAmC,kDAAkD,GAC1F,IACE;AAAA,OACN;AAAA,IACC,aACC,qBAAC,SAAI,WAAU,sHACb;AAAA,0BAAC,UAAM,YAAE,0CAA0C,kDAAkD,GAAE;AAAA,MACvG,oBAAC,OAAE,MAAM,YAAY,WAAU,4CAA2C,QAAO,UAAS,KAAI,cAC3F,YAAE,wCAAwC,qBAAqB,GAClE;AAAA,OACF,IACE;AAAA,IACJ,qBAAC,SAAI,WAAU,aACb;AAAA,2BAAC,SAAI,WAAU,2EACb;AAAA,6BAAC,SAAI,WAAU,0CACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,IAAI;AAAA,cACJ,SAAS;AAAA,cACT,iBAAiB,CAAC,YAAY;AAC5B,sBAAM,UAAU,YAAY;AAC5B,yBAAS,EAAE,OAAO,SAAS,cAAc,UAAU,SAAY,KAAK,YAAY,aAAa,CAAC;AAAA,cAChG;AAAA,cACA,UAAU,CAAC;AAAA;AAAA,UACb;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAW,aAAa,+BAA+B;AAAA,cAEtD,YAAE,2CAA2C,kCAAkC;AAAA;AAAA,UAClF;AAAA,WACF;AAAA,QACA,qBAAC,SAAI,WAAU,0CACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,IAAI;AAAA,cACJ,SAAS,CAAC,WAAW;AAAA,cACrB,iBAAiB,CAAC,YAAY,SAAS,EAAE,wBAAwB,YAAY,KAAK,CAAC;AAAA,cACnF,UAAU;AAAA,cACV,oBAAkB,UAAU,qBAAqB;AAAA;AAAA,UACnD;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAW,CAAC,uBAAuB,+BAA+B;AAAA,cAEjE,YAAE,+CAA+C,oCAAoC;AAAA;AAAA,UACxF;AAAA,WACF;AAAA,SACF;AAAA,MACC,UACC,oBAAC,OAAE,IAAI,oBAAoB,WAAU,iCAClC;AAAA,QACC;AAAA,QACA;AAAA,MACF,GACF,IACE;AAAA,OACN;AAAA,IACC,cAAc,CAAC,UACd;AAAA,MAAC;AAAA;AAAA,QACC,cAAc;AAAA,QACd,cAAc,OAAO,KAAK,YAAY,iBAAiB,WAAW,IAAI,WAAW,eAAe;AAAA,QAChG,UAAU,CAAC,UAAU,SAAS,EAAE,cAAc,SAAS,OAAU,CAAC;AAAA;AAAA,IACpE,IACE,cAAc,UAChB,oBAAC,SAAI,WAAU,0CACb,8BAAC,OAAE,IAAI,oBAAoB,WAAU,iCAClC;AAAA,MACC;AAAA,MACA;AAAA,IACF,GACF,GACF,IACE;AAAA,KACN;AAEJ;AAEA,SAAS,qBAAqB,EAAE,OAAO,UAAU,UAAU,IAAI,GAAU;AACvE,QAAM,IAAI,KAAK;AACf,QAAM,eAAe,KAAK;AAC1B,MAAI,CAAC,cAAc;AACjB,WACE,oBAAC,SAAI,WAAU,kEACZ,YAAE,0CAA0C,oCAAoC,GACnF;AAAA,EAEJ;AACA,QAAM,kBAAkB,OAAO,UAAU,WAAW,QAAQ,MAAM,QAAQ,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,EAAE,IAAI;AAC5G,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO,mBAAmB;AAAA,MAC1B,UAAU,CAAC,SAAS,SAAS,QAAQ,MAAS;AAAA,MAC9C,mBAAmB,KAAK,2BAA2B;AAAA,MACnD;AAAA;AAAA,EACF;AAEJ;AAEA,cAAc,SAAS,cAAc;AAAA,EACnC,OAAO;AAAA,EACP,WAAW,CAAC,UAAU,oBAAC,4BAA0B,GAAG,OAAO;AAC7D,CAAC;",
6
6
  "names": []
7
7
  }
@@ -2,6 +2,7 @@ const metadata = {
2
2
  requireAuth: true,
3
3
  requireFeatures: ["entities.definitions.manage"],
4
4
  pageTitle: "Edit Definitions",
5
+ pageTitleKey: "entities.userEntities.edit.pageTitle",
5
6
  pageGroup: "Data designer",
6
7
  navHidden: true
7
8
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/entities/backend/entities/system/%5BentityId%5D/page.meta.ts"],
4
- "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['entities.definitions.manage'],\n pageTitle: 'Edit Definitions',\n pageGroup: 'Data designer',\n navHidden: true,\n}\n"],
5
- "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,6BAA6B;AAAA,EAC/C,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AACb;",
4
+ "sourcesContent": ["export const metadata = {\n requireAuth: true,\n requireFeatures: ['entities.definitions.manage'],\n pageTitle: 'Edit Definitions',\n pageTitleKey: 'entities.userEntities.edit.pageTitle',\n pageGroup: 'Data designer',\n navHidden: true,\n}\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,aAAa;AAAA,EACb,iBAAiB,CAAC,6BAA6B;AAAA,EAC/C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AACb;",
6
6
  "names": []
7
7
  }
@@ -149,7 +149,7 @@ function EditDefinitionsPage({ params }) {
149
149
  const entJson = await readApiResultOrThrow(
150
150
  "/api/entities/entities",
151
151
  void 0,
152
- { errorMessage: "Failed to load entity metadata", fallback: { items: [] } }
152
+ { errorMessage: t("entities.userEntities.edit.errors.loadMetadataFailed", "Failed to load entity metadata"), fallback: { items: [] } }
153
153
  );
154
154
  const ent = (entJson.items || []).find((x) => x.entityId === entityId);
155
155
  if (mounted) {
@@ -175,7 +175,7 @@ function EditDefinitionsPage({ params }) {
175
175
  const json = await readApiResultOrThrow(
176
176
  `/api/entities/definitions.manage?entityId=${encodeURIComponent(entityId)}`,
177
177
  void 0,
178
- { errorMessage: "Failed to load entity definitions", fallback: { items: [], deletedKeys: [] } }
178
+ { errorMessage: t("entities.userEntities.edit.errors.loadDefinitionsFailed", "Failed to load entity definitions"), fallback: { items: [], deletedKeys: [] } }
179
179
  );
180
180
  if (mounted) {
181
181
  const loaded = (json.items || []).map((d) => ({ key: d.key, kind: d.kind, configJson: d.configJson || {}, isActive: d.isActive !== false }));
@@ -198,7 +198,7 @@ function EditDefinitionsPage({ params }) {
198
198
  setSingleFieldsetPerRecord(json.settings?.singleFieldsetPerRecord !== false);
199
199
  }
200
200
  } catch (e) {
201
- if (mounted) setError(e.message || "Failed to load");
201
+ if (mounted) setError(e.message || t("entities.userEntities.edit.errors.loadFailed", "Failed to load"));
202
202
  } finally {
203
203
  if (mounted) setLoading(false);
204
204
  }
@@ -207,7 +207,7 @@ function EditDefinitionsPage({ params }) {
207
207
  return () => {
208
208
  mounted = false;
209
209
  };
210
- }, [entityId]);
210
+ }, [entityId, t]);
211
211
  function addField() {
212
212
  setDefs((arr) => [
213
213
  ...arr,
@@ -227,12 +227,12 @@ function EditDefinitionsPage({ params }) {
227
227
  body: JSON.stringify({ entityId, key })
228
228
  });
229
229
  if (!call.ok) {
230
- await raiseCrudError(call.response, "Failed to restore field");
230
+ await raiseCrudError(call.response, t("entities.userEntities.edit.errors.restoreFieldFailed", "Failed to restore field"));
231
231
  }
232
232
  const j2 = await readApiResultOrThrow(
233
233
  `/api/entities/definitions.manage?entityId=${encodeURIComponent(entityId)}`,
234
234
  void 0,
235
- { errorMessage: "Failed to reload field definitions", fallback: { items: [], deletedKeys: [] } }
235
+ { errorMessage: t("entities.userEntities.edit.errors.reloadDefinitionsFailed", "Failed to reload field definitions"), fallback: { items: [], deletedKeys: [] } }
236
236
  );
237
237
  const loaded = (j2.items || []).map((d) => ({ key: d.key, kind: d.kind, configJson: d.configJson || {}, isActive: d.isActive !== false }));
238
238
  loaded.sort(
@@ -241,10 +241,10 @@ function EditDefinitionsPage({ params }) {
241
241
  setDefs(loaded);
242
242
  setDefsVersion(readVersionToken(j2.version));
243
243
  setDeletedKeys(Array.isArray(j2.deletedKeys) ? j2.deletedKeys : []);
244
- flash(`Restored ${key}`, "success");
244
+ flash(t("entities.userEntities.edit.flash.restoredField", "Restored {{key}}", { key }), "success");
245
245
  await invalidateCustomFieldDefs(queryClient, entityId);
246
246
  } catch (e) {
247
- flash(e?.message || "Failed to restore field", "error");
247
+ flash(e?.message || t("entities.userEntities.edit.errors.restoreFieldFailed", "Failed to restore field"), "error");
248
248
  }
249
249
  }
250
250
  async function saveAll() {
@@ -252,8 +252,8 @@ function EditDefinitionsPage({ params }) {
252
252
  setError(null);
253
253
  try {
254
254
  if (!validateAll()) {
255
- flash("Please fix validation errors in field definitions", "error");
256
- throw new Error("Validation failed");
255
+ flash(t("entities.customFields.errors.validation", "Please fix validation errors in field definitions."), "error");
256
+ throw new Error(t("entities.userEntities.edit.errors.validationFailed", "Validation failed"));
257
257
  }
258
258
  const payload = {
259
259
  entityId,
@@ -274,13 +274,13 @@ function EditDefinitionsPage({ params }) {
274
274
  );
275
275
  if (!call.ok) {
276
276
  if (surfaceRecordConflict({ status: call.status, body: call.result }, t)) return;
277
- await raiseCrudError(call.response, "Failed to save definitions");
277
+ await raiseCrudError(call.response, t("entities.customFields.errors.saveFailed", "Failed to save field definitions."));
278
278
  }
279
279
  setDefsVersion(readVersionToken(call.result?.version));
280
280
  await invalidateCustomFieldDefs(queryClient, entityId);
281
- router.push(`/backend/entities/user?flash=Definitions%20saved&type=success`);
281
+ router.push(`/backend/entities/user?flash=${encodeURIComponent(t("entities.customFields.flash.saved", "Definitions saved"))}&type=success`);
282
282
  } catch (e) {
283
- setError(e.message || "Failed to save");
283
+ setError(e.message || t("entities.customFields.errors.saveFailed", "Failed to save field definitions."));
284
284
  } finally {
285
285
  setSaving(false);
286
286
  }
@@ -296,11 +296,11 @@ function EditDefinitionsPage({ params }) {
296
296
  body: JSON.stringify({ entityId, key: def.key })
297
297
  });
298
298
  if (!call.ok) {
299
- await raiseCrudError(call.response, "Failed to delete field");
299
+ await raiseCrudError(call.response, t("entities.customFields.errors.deleteFailed", "Failed to delete field."));
300
300
  }
301
301
  setDefsVersion(readVersionToken(call.result?.version));
302
302
  } catch (error2) {
303
- const message = error2 instanceof Error ? error2.message : "Failed to delete field";
303
+ const message = error2 instanceof Error ? error2.message : t("entities.customFields.errors.deleteFailed", "Failed to delete field.");
304
304
  flash(message, "error");
305
305
  return;
306
306
  }
@@ -341,7 +341,7 @@ function EditDefinitionsPage({ params }) {
341
341
  if (!orderDirty) return;
342
342
  setOrderSaving(true);
343
343
  try {
344
- if (!validateAll()) throw new Error("Validation failed");
344
+ if (!validateAll()) throw new Error(t("entities.userEntities.edit.errors.validationFailed", "Validation failed"));
345
345
  const payload = {
346
346
  entityId,
347
347
  definitions: defs.filter((d) => !!d.key).map((d) => ({
@@ -364,14 +364,14 @@ function EditDefinitionsPage({ params }) {
364
364
  setOrderDirty(false);
365
365
  return;
366
366
  }
367
- await raiseCrudError(call.response, "Failed to save order");
367
+ await raiseCrudError(call.response, t("entities.userEntities.edit.errors.saveOrderFailed", "Failed to save order"));
368
368
  }
369
369
  setDefsVersion(readVersionToken(call.result?.version));
370
370
  setOrderDirty(false);
371
- flash("Order saved", "success");
371
+ flash(t("entities.userEntities.edit.flash.orderSaved", "Order saved"), "success");
372
372
  await invalidateCustomFieldDefs(queryClient, entityId);
373
373
  } catch (e) {
374
- flash(e?.message || "Failed to save order", "error");
374
+ flash(e?.message || t("entities.userEntities.edit.errors.saveOrderFailed", "Failed to save order"), "error");
375
375
  } finally {
376
376
  setOrderSaving(false);
377
377
  }
@@ -384,21 +384,21 @@ function EditDefinitionsPage({ params }) {
384
384
  });
385
385
  const metadataFieldsReadOnly = entitySource === "code";
386
386
  const fields = [
387
- { id: "label", label: "Label", type: "text", required: true, readOnly: metadataFieldsReadOnly },
388
- { id: "description", label: "Description", type: "textarea", readOnly: metadataFieldsReadOnly },
387
+ { id: "label", label: t("entities.userEntities.form.label.label", "Label"), type: "text", required: true, readOnly: metadataFieldsReadOnly },
388
+ { id: "description", label: t("entities.userEntities.form.description.label", "Description"), type: "textarea", readOnly: metadataFieldsReadOnly },
389
389
  {
390
390
  id: "defaultEditor",
391
- label: "Default Editor (multiline)",
391
+ label: t("entities.userEntities.form.defaultEditor.label", "Default Editor (multiline)"),
392
392
  type: "select",
393
393
  readOnly: metadataFieldsReadOnly,
394
394
  options: [
395
- { value: "", label: "Default (Markdown)" },
396
- { value: "markdown", label: "Markdown (UIW)" },
397
- { value: "simpleMarkdown", label: "Simple Markdown" },
398
- { value: "htmlRichText", label: "HTML Rich Text" }
395
+ { value: "", label: t("entities.userEntities.form.defaultEditor.options.default", "Default (Markdown)") },
396
+ { value: "markdown", label: t("entities.userEntities.form.defaultEditor.options.markdown", "Markdown (UIW)") },
397
+ { value: "simpleMarkdown", label: t("entities.userEntities.form.defaultEditor.options.simpleMarkdown", "Simple Markdown") },
398
+ { value: "htmlRichText", label: t("entities.userEntities.form.defaultEditor.options.htmlRichText", "HTML Rich Text") }
399
399
  ]
400
400
  },
401
- ...entitySource === "custom" ? [{ id: "showInSidebar", label: "Show in sidebar", type: "checkbox" }] : []
401
+ ...entitySource === "custom" ? [{ id: "showInSidebar", label: t("entities.userEntities.form.showInSidebar.label", "Show in sidebar"), type: "checkbox" }] : []
402
402
  ];
403
403
  const renderFieldDefinitions = React.useCallback(
404
404
  () => /* @__PURE__ */ jsx(
@@ -441,7 +441,7 @@ function EditDefinitionsPage({ params }) {
441
441
  });
442
442
  setOrderDirty(true);
443
443
  },
444
- orderNotice: orderDirty ? { dirty: true, saving: orderSaving, message: "Reordered \u2014 will auto-save on blur" } : void 0,
444
+ orderNotice: orderDirty ? { dirty: true, saving: orderSaving, message: t("entities.userEntities.edit.orderNotice", "Reordered - will auto-save on blur") } : void 0,
445
445
  addButtonLabel: t("entities.customFields.editor.addField", "Add Field"),
446
446
  translate: t,
447
447
  listRef,
@@ -458,31 +458,31 @@ function EditDefinitionsPage({ params }) {
458
458
  }
459
459
  }
460
460
  ),
461
- [defs, defErrors, deletedKeys, fieldsets, activeFieldset, singleFieldsetPerRecord, orderDirty, orderSaving, addField, removeField, restoreField, saveOrderIfDirty]
461
+ [defs, defErrors, deletedKeys, fieldsets, activeFieldset, singleFieldsetPerRecord, orderDirty, orderSaving, addField, removeField, restoreField, saveOrderIfDirty, t]
462
462
  );
463
- const definitionsGroup = { id: "definitions", title: "Field Definitions", column: 1, component: renderFieldDefinitions };
463
+ const definitionsGroup = { id: "definitions", title: t("entities.userEntities.edit.groups.definitions", "Field Definitions"), column: 1, component: renderFieldDefinitions };
464
464
  const groups = [
465
- { id: "settings", title: "Entity Settings", column: 1, fields: entitySource === "custom" ? ["label", "description", "defaultEditor", "showInSidebar"] : ["label", "description", "defaultEditor"] },
465
+ { id: "settings", title: t("entities.userEntities.edit.groups.settings", "Entity Settings"), column: 1, fields: entitySource === "custom" ? ["label", "description", "defaultEditor", "showInSidebar"] : ["label", "description", "defaultEditor"] },
466
466
  definitionsGroup
467
467
  ];
468
468
  const handleCrudFormSubmit = React.useCallback(async (vals) => {
469
469
  if (!entityId) {
470
- throw createCrudFormError("Invalid entity ID");
470
+ throw createCrudFormError(t("entities.userEntities.edit.errors.invalidEntityId", "Invalid entity ID"));
471
471
  }
472
472
  if (!validateAll()) {
473
- flash("Please fix validation errors in field definitions", "error");
474
- throw createCrudFormError("Please fix validation errors in field definitions");
473
+ flash(t("entities.customFields.errors.validation", "Please fix validation errors in field definitions."), "error");
474
+ throw createCrudFormError(t("entities.customFields.errors.validation", "Please fix validation errors in field definitions."));
475
475
  }
476
476
  if (shouldRegisterEntityMetadata(entitySource)) {
477
477
  const entityPayload = buildEntityMetadataPayload(entitySource, vals);
478
- if (!entityPayload) throw createCrudFormError("Validation failed");
478
+ if (!entityPayload) throw createCrudFormError(t("entities.userEntities.edit.errors.validationFailed", "Validation failed"));
479
479
  const callEntity = await apiCall("/api/entities/entities", {
480
480
  method: "POST",
481
481
  headers: { "content-type": "application/json" },
482
482
  body: JSON.stringify({ entityId, ...entityPayload })
483
483
  });
484
484
  if (!callEntity.ok) {
485
- await raiseCrudError(callEntity.response, "Failed to save entity");
485
+ await raiseCrudError(callEntity.response, t("entities.userEntities.edit.errors.saveEntityFailed", "Failed to save entity"));
486
486
  }
487
487
  try {
488
488
  window.dispatchEvent(new Event("om:refresh-sidebar"));
@@ -504,7 +504,7 @@ function EditDefinitionsPage({ params }) {
504
504
  })
505
505
  );
506
506
  if (!callDefs.ok) {
507
- await raiseCrudError(callDefs.response, "Failed to save definitions");
507
+ await raiseCrudError(callDefs.response, t("entities.customFields.errors.saveFailed", "Failed to save field definitions."));
508
508
  }
509
509
  setDefsVersion(readVersionToken(callDefs.result?.version));
510
510
  try {
@@ -512,12 +512,12 @@ function EditDefinitionsPage({ params }) {
512
512
  } catch {
513
513
  }
514
514
  await invalidateCustomFieldDefs(queryClient, entityId);
515
- flash("Definitions saved", "success");
516
- }, [buildFieldsetPayload, defs, defsVersion, entityId, entitySource, queryClient, singleFieldsetPerRecord, validateAll]);
515
+ flash(t("entities.customFields.flash.saved", "Definitions saved"), "success");
516
+ }, [buildFieldsetPayload, defs, defsVersion, entityId, entitySource, queryClient, singleFieldsetPerRecord, t, validateAll]);
517
517
  if (!entityId) {
518
518
  return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
519
- /* @__PURE__ */ jsx(AlertTitle, { children: "Invalid entity" }),
520
- /* @__PURE__ */ jsx(AlertDescription, { children: "The requested entity ID is missing or invalid." })
519
+ /* @__PURE__ */ jsx(AlertTitle, { children: t("entities.userEntities.edit.errors.invalidEntityTitle", "Invalid entity") }),
520
+ /* @__PURE__ */ jsx(AlertDescription, { children: t("entities.userEntities.edit.errors.invalidEntityDescription", "The requested entity ID is missing or invalid.") })
521
521
  ] }) }) }) });
522
522
  }
523
523
  if (embedFieldsetView) {
@@ -525,12 +525,12 @@ function EditDefinitionsPage({ params }) {
525
525
  CrudForm,
526
526
  {
527
527
  schema: entityFormSchema,
528
- title: `Edit fieldset: ${requestedFieldset ?? entityId}`,
528
+ title: t("entities.userEntities.edit.fieldsetTitle", "Edit fieldset: {{name}}", { name: requestedFieldset ?? entityId }),
529
529
  fields: [],
530
530
  groups: [definitionsGroup],
531
531
  initialValues: entityInitial,
532
532
  isLoading: entityFormLoading || loading,
533
- submitLabel: "Save",
533
+ submitLabel: t("entities.userEntities.records.form.submitSave", "Save"),
534
534
  deleteVisible: false,
535
535
  backHref: void 0,
536
536
  cancelHref: void 0,
@@ -544,24 +544,24 @@ function EditDefinitionsPage({ params }) {
544
544
  CrudForm,
545
545
  {
546
546
  schema: entityFormSchema,
547
- title: `Edit Entity: ${entityId}`,
547
+ title: t("entities.userEntities.edit.title", "Edit Entity: {{entityId}}", { entityId }),
548
548
  backHref: entitySource === "code" ? "/backend/entities/system" : "/backend/entities/user",
549
549
  fields,
550
550
  groups,
551
551
  initialValues: entityInitial,
552
552
  isLoading: entityFormLoading || loading,
553
- submitLabel: "Save",
553
+ submitLabel: t("entities.userEntities.records.form.submitSave", "Save"),
554
554
  deleteVisible: entitySource === "custom",
555
- extraActions: entitySource === "custom" ? /* @__PURE__ */ jsx(Button, { variant: "outline", asChild: true, children: /* @__PURE__ */ jsx(Link, { href: `/backend/entities/user/${encodeURIComponent(entityId)}/records`, children: "Show Records" }) }) : null,
555
+ extraActions: entitySource === "custom" ? /* @__PURE__ */ jsx(Button, { variant: "outline", asChild: true, children: /* @__PURE__ */ jsx(Link, { href: `/backend/entities/user/${encodeURIComponent(entityId)}/records`, children: t("entities.userEntities.edit.showRecords", "Show Records") }) }) : null,
556
556
  cancelHref: entitySource === "code" ? "/backend/entities/system" : "/backend/entities/user",
557
- successRedirect: entitySource === "code" ? "/backend/entities/system?flash=Definitions%20saved&type=success" : "/backend/entities/user?flash=Definitions%20saved&type=success",
557
+ successRedirect: entitySource === "code" ? `/backend/entities/system?flash=${encodeURIComponent(t("entities.customFields.flash.saved", "Definitions saved"))}&type=success` : `/backend/entities/user?flash=${encodeURIComponent(t("entities.customFields.flash.saved", "Definitions saved"))}&type=success`,
558
558
  onSubmit: handleCrudFormSubmit,
559
559
  onDelete: entitySource === "custom" ? async () => {
560
560
  const callDelete = await apiCall("/api/entities/entities", { method: "DELETE", headers: { "content-type": "application/json" }, body: JSON.stringify({ entityId }) });
561
561
  if (!callDelete.ok) {
562
- await raiseCrudError(callDelete.response, "Failed to delete entity");
562
+ await raiseCrudError(callDelete.response, t("entities.userEntities.edit.errors.deleteEntityFailed", "Failed to delete entity"));
563
563
  }
564
- flash("Entity deleted", "success");
564
+ flash(t("entities.userEntities.edit.flash.entityDeleted", "Entity deleted"), "success");
565
565
  try {
566
566
  window.dispatchEvent(new Event("om:refresh-sidebar"));
567
567
  } catch {