@wordrhyme/auto-crud 1.0.1 → 1.0.2

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.
package/dist/index.cjs CHANGED
@@ -4014,8 +4014,7 @@ function createSelectColumn() {
4014
4014
  /**
4015
4015
  * 创建操作列
4016
4016
  */
4017
- function createActionsColumn(config) {
4018
- const { onEdit, onDelete, onView, onCopy } = config;
4017
+ function createActionsColumn(items) {
4019
4018
  return {
4020
4019
  id: "actions",
4021
4020
  cell: ({ row }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuTrigger, {
@@ -4026,29 +4025,14 @@ function createActionsColumn(config) {
4026
4025
  className: "flex size-8 p-0 data-[state=open]:bg-muted",
4027
4026
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Ellipsis, { className: "size-4" })
4028
4027
  })
4029
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DropdownMenuContent, {
4028
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuContent, {
4030
4029
  align: "end",
4031
4030
  className: "w-40",
4032
- children: [
4033
- onView && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
4034
- onClick: () => onView(row.original),
4035
- children: "查看"
4036
- }),
4037
- onEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
4038
- onClick: () => onEdit(row.original),
4039
- children: "编辑"
4040
- }),
4041
- onCopy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
4042
- onClick: () => onCopy(row.original),
4043
- children: "复制"
4044
- }),
4045
- (onView || onEdit || onCopy) && onDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuSeparator, {}),
4046
- onDelete && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
4047
- className: "text-destructive",
4048
- onClick: () => onDelete(row.original),
4049
- children: "删除"
4050
- })
4051
- ]
4031
+ children: items.map((item, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [item.separator && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuSeparator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DropdownMenuItem, {
4032
+ className: item.variant === "destructive" ? "text-destructive" : "",
4033
+ onClick: () => item.onClick(row.original),
4034
+ children: item.label
4035
+ })] }, i))
4052
4036
  })] }),
4053
4037
  size: 40
4054
4038
  };
@@ -4936,10 +4920,462 @@ function AutoFormInner({ schema: zodSchema, initialValues, onSubmit, overrides,
4936
4920
  }
4937
4921
  const AutoForm = (0, react.forwardRef)(AutoFormInner);
4938
4922
 
4923
+ //#endregion
4924
+ //#region src/i18n/locale.ts
4925
+ const zhCN = {
4926
+ toolbar: {
4927
+ create: "新建",
4928
+ import: "导入",
4929
+ export: "导出",
4930
+ exportSelected: (count) => `导出(${count})`
4931
+ },
4932
+ rowActions: {
4933
+ view: "查看",
4934
+ edit: "编辑",
4935
+ copy: "复制",
4936
+ delete: "删除"
4937
+ },
4938
+ viewModal: { title: "详情" },
4939
+ boolean: {
4940
+ true: "是",
4941
+ false: "否"
4942
+ },
4943
+ formModal: {
4944
+ createTitle: "新建",
4945
+ editTitle: "编辑",
4946
+ cancel: "取消",
4947
+ create: "创建",
4948
+ save: "保存",
4949
+ submitting: "处理中..."
4950
+ },
4951
+ deleteModal: {
4952
+ title: "确认删除",
4953
+ description: "此操作无法撤销。确定要删除这条记录吗?",
4954
+ cancel: "取消",
4955
+ confirm: "确认删除",
4956
+ confirming: "删除中..."
4957
+ },
4958
+ importDialog: {
4959
+ title: "导入数据",
4960
+ uploadDescription: "上传 CSV 或 JSON 文件以批量导入数据",
4961
+ previewDescription: (count) => `已解析 ${count} 条数据,确认后开始导入`,
4962
+ importingDescription: "正在导入数据...",
4963
+ doneDescription: "导入完成",
4964
+ dragHint: "拖拽文件到此处,或点击选择文件",
4965
+ formatHint: "支持 CSV、JSON 格式",
4966
+ downloadTemplate: "下载 CSV 模板",
4967
+ moreColumns: (count) => `+${count} 列`,
4968
+ previewSummary: (rows, fields, format, previewLimit) => `共 ${rows} 条数据${previewLimit ? `(预览前 ${previewLimit} 条)` : ""},${fields} 个字段,格式: ${format.toUpperCase()}`,
4969
+ reselect: "重新选择",
4970
+ confirmImport: "确认导入",
4971
+ importingRows: (count) => `正在导入 ${count} 条数据...`,
4972
+ resultCreated: "新建",
4973
+ resultUpdated: "更新",
4974
+ resultSkipped: "跳过",
4975
+ resultFailed: "验证失败",
4976
+ failedRowHeader: "行号",
4977
+ failedErrorHeader: "错误",
4978
+ close: "关闭",
4979
+ continueImport: "继续导入",
4980
+ errorNoData: "文件中没有数据行",
4981
+ errorParseFailed: "文件解析失败",
4982
+ errorImportFailed: "导入失败"
4983
+ }
4984
+ };
4985
+ const enUS = {
4986
+ toolbar: {
4987
+ create: "New",
4988
+ import: "Import",
4989
+ export: "Export",
4990
+ exportSelected: (count) => `Export (${count})`
4991
+ },
4992
+ rowActions: {
4993
+ view: "View",
4994
+ edit: "Edit",
4995
+ copy: "Copy",
4996
+ delete: "Delete"
4997
+ },
4998
+ viewModal: { title: "Details" },
4999
+ boolean: {
5000
+ true: "Yes",
5001
+ false: "No"
5002
+ },
5003
+ formModal: {
5004
+ createTitle: "New",
5005
+ editTitle: "Edit",
5006
+ cancel: "Cancel",
5007
+ create: "Create",
5008
+ save: "Save",
5009
+ submitting: "Processing..."
5010
+ },
5011
+ deleteModal: {
5012
+ title: "Confirm Delete",
5013
+ description: "This action cannot be undone. Are you sure you want to delete this record?",
5014
+ cancel: "Cancel",
5015
+ confirm: "Delete",
5016
+ confirming: "Deleting..."
5017
+ },
5018
+ importDialog: {
5019
+ title: "Import Data",
5020
+ uploadDescription: "Upload a CSV or JSON file to bulk import data",
5021
+ previewDescription: (count) => `Parsed ${count} records, confirm to start importing`,
5022
+ importingDescription: "Importing data...",
5023
+ doneDescription: "Import complete",
5024
+ dragHint: "Drag file here, or click to select",
5025
+ formatHint: "Supports CSV, JSON formats",
5026
+ downloadTemplate: "Download CSV Template",
5027
+ moreColumns: (count) => `+${count} more`,
5028
+ previewSummary: (rows, fields, format, previewLimit) => `${rows} records${previewLimit ? ` (preview first ${previewLimit})` : ""}, ${fields} fields, format: ${format.toUpperCase()}`,
5029
+ reselect: "Reselect",
5030
+ confirmImport: "Confirm Import",
5031
+ importingRows: (count) => `Importing ${count} records...`,
5032
+ resultCreated: "Created",
5033
+ resultUpdated: "Updated",
5034
+ resultSkipped: "Skipped",
5035
+ resultFailed: "Failed",
5036
+ failedRowHeader: "Row",
5037
+ failedErrorHeader: "Error",
5038
+ close: "Close",
5039
+ continueImport: "Import More",
5040
+ errorNoData: "No data rows found in file",
5041
+ errorParseFailed: "Failed to parse file",
5042
+ errorImportFailed: "Import failed"
5043
+ }
5044
+ };
5045
+ const jaJP = {
5046
+ toolbar: {
5047
+ create: "新規作成",
5048
+ import: "インポート",
5049
+ export: "エクスポート",
5050
+ exportSelected: (count) => `エクスポート(${count})`
5051
+ },
5052
+ rowActions: {
5053
+ view: "詳細",
5054
+ edit: "編集",
5055
+ copy: "コピー",
5056
+ delete: "削除"
5057
+ },
5058
+ viewModal: { title: "詳細" },
5059
+ boolean: {
5060
+ true: "はい",
5061
+ false: "いいえ"
5062
+ },
5063
+ formModal: {
5064
+ createTitle: "新規作成",
5065
+ editTitle: "編集",
5066
+ cancel: "キャンセル",
5067
+ create: "作成",
5068
+ save: "保存",
5069
+ submitting: "処理中..."
5070
+ },
5071
+ deleteModal: {
5072
+ title: "削除の確認",
5073
+ description: "この操作は元に戻せません。このレコードを削除してもよろしいですか?",
5074
+ cancel: "キャンセル",
5075
+ confirm: "削除する",
5076
+ confirming: "削除中..."
5077
+ },
5078
+ importDialog: {
5079
+ title: "データのインポート",
5080
+ uploadDescription: "CSVまたはJSONファイルをアップロードして一括インポート",
5081
+ previewDescription: (count) => `${count}件のデータを解析しました。確認してインポートを開始します`,
5082
+ importingDescription: "データをインポート中...",
5083
+ doneDescription: "インポート完了",
5084
+ dragHint: "ファイルをここにドラッグするか、クリックして選択",
5085
+ formatHint: "CSV・JSON形式に対応",
5086
+ downloadTemplate: "CSVテンプレートをダウンロード",
5087
+ moreColumns: (count) => `+${count}列`,
5088
+ previewSummary: (rows, fields, format, previewLimit) => `${rows}件${previewLimit ? `(上位${previewLimit}件プレビュー)` : ""}、${fields}フィールド、形式: ${format.toUpperCase()}`,
5089
+ reselect: "再選択",
5090
+ confirmImport: "インポートを確認",
5091
+ importingRows: (count) => `${count}件をインポート中...`,
5092
+ resultCreated: "新規作成",
5093
+ resultUpdated: "更新",
5094
+ resultSkipped: "スキップ",
5095
+ resultFailed: "失敗",
5096
+ failedRowHeader: "行番号",
5097
+ failedErrorHeader: "エラー",
5098
+ close: "閉じる",
5099
+ continueImport: "続けてインポート",
5100
+ errorNoData: "ファイルにデータ行がありません",
5101
+ errorParseFailed: "ファイルの解析に失敗しました",
5102
+ errorImportFailed: "インポートに失敗しました"
5103
+ }
5104
+ };
5105
+ const koKR = {
5106
+ toolbar: {
5107
+ create: "새로 만들기",
5108
+ import: "가져오기",
5109
+ export: "내보내기",
5110
+ exportSelected: (count) => `내보내기(${count})`
5111
+ },
5112
+ rowActions: {
5113
+ view: "보기",
5114
+ edit: "편집",
5115
+ copy: "복사",
5116
+ delete: "삭제"
5117
+ },
5118
+ viewModal: { title: "상세 정보" },
5119
+ boolean: {
5120
+ true: "예",
5121
+ false: "아니요"
5122
+ },
5123
+ formModal: {
5124
+ createTitle: "새로 만들기",
5125
+ editTitle: "편집",
5126
+ cancel: "취소",
5127
+ create: "만들기",
5128
+ save: "저장",
5129
+ submitting: "처리 중..."
5130
+ },
5131
+ deleteModal: {
5132
+ title: "삭제 확인",
5133
+ description: "이 작업은 취소할 수 없습니다. 이 레코드를 삭제하시겠습니까?",
5134
+ cancel: "취소",
5135
+ confirm: "삭제",
5136
+ confirming: "삭제 중..."
5137
+ },
5138
+ importDialog: {
5139
+ title: "데이터 가져오기",
5140
+ uploadDescription: "CSV 또는 JSON 파일을 업로드하여 일괄 가져오기",
5141
+ previewDescription: (count) => `${count}개의 데이터를 분석했습니다. 확인 후 가져오기를 시작합니다`,
5142
+ importingDescription: "데이터를 가져오는 중...",
5143
+ doneDescription: "가져오기 완료",
5144
+ dragHint: "파일을 여기에 드래그하거나 클릭하여 선택",
5145
+ formatHint: "CSV, JSON 형식 지원",
5146
+ downloadTemplate: "CSV 템플릿 다운로드",
5147
+ moreColumns: (count) => `+${count}열 더`,
5148
+ previewSummary: (rows, fields, format, previewLimit) => `${rows}개 레코드${previewLimit ? ` (상위 ${previewLimit}개 미리보기)` : ""}, ${fields}개 필드, 형식: ${format.toUpperCase()}`,
5149
+ reselect: "다시 선택",
5150
+ confirmImport: "가져오기 확인",
5151
+ importingRows: (count) => `${count}개의 레코드를 가져오는 중...`,
5152
+ resultCreated: "생성됨",
5153
+ resultUpdated: "업데이트됨",
5154
+ resultSkipped: "건너뜀",
5155
+ resultFailed: "실패",
5156
+ failedRowHeader: "행 번호",
5157
+ failedErrorHeader: "오류",
5158
+ close: "닫기",
5159
+ continueImport: "계속 가져오기",
5160
+ errorNoData: "파일에 데이터 행이 없습니다",
5161
+ errorParseFailed: "파일 파싱에 실패했습니다",
5162
+ errorImportFailed: "가져오기에 실패했습니다"
5163
+ }
5164
+ };
5165
+ const frFR = {
5166
+ toolbar: {
5167
+ create: "Nouveau",
5168
+ import: "Importer",
5169
+ export: "Exporter",
5170
+ exportSelected: (count) => `Exporter (${count})`
5171
+ },
5172
+ rowActions: {
5173
+ view: "Voir",
5174
+ edit: "Modifier",
5175
+ copy: "Copier",
5176
+ delete: "Supprimer"
5177
+ },
5178
+ viewModal: { title: "Détails" },
5179
+ boolean: {
5180
+ true: "Oui",
5181
+ false: "Non"
5182
+ },
5183
+ formModal: {
5184
+ createTitle: "Nouveau",
5185
+ editTitle: "Modifier",
5186
+ cancel: "Annuler",
5187
+ create: "Créer",
5188
+ save: "Enregistrer",
5189
+ submitting: "En cours..."
5190
+ },
5191
+ deleteModal: {
5192
+ title: "Confirmer la suppression",
5193
+ description: "Cette action est irréversible. Voulez-vous vraiment supprimer cet enregistrement ?",
5194
+ cancel: "Annuler",
5195
+ confirm: "Supprimer",
5196
+ confirming: "Suppression..."
5197
+ },
5198
+ importDialog: {
5199
+ title: "Importer des données",
5200
+ uploadDescription: "Téléchargez un fichier CSV ou JSON pour importer en masse",
5201
+ previewDescription: (count) => `${count} enregistrements analysés, confirmez pour démarrer l'import`,
5202
+ importingDescription: "Importation en cours...",
5203
+ doneDescription: "Import terminé",
5204
+ dragHint: "Glissez un fichier ici ou cliquez pour sélectionner",
5205
+ formatHint: "Formats CSV et JSON acceptés",
5206
+ downloadTemplate: "Télécharger le modèle CSV",
5207
+ moreColumns: (count) => `+${count} colonnes`,
5208
+ previewSummary: (rows, fields, format, previewLimit) => `${rows} enregistrements${previewLimit ? ` (aperçu des ${previewLimit} premiers)` : ""}, ${fields} champs, format : ${format.toUpperCase()}`,
5209
+ reselect: "Resélectionner",
5210
+ confirmImport: "Confirmer l'import",
5211
+ importingRows: (count) => `Importation de ${count} enregistrements...`,
5212
+ resultCreated: "Créés",
5213
+ resultUpdated: "Mis à jour",
5214
+ resultSkipped: "Ignorés",
5215
+ resultFailed: "Échoués",
5216
+ failedRowHeader: "Ligne",
5217
+ failedErrorHeader: "Erreur",
5218
+ close: "Fermer",
5219
+ continueImport: "Continuer l'import",
5220
+ errorNoData: "Aucune ligne de données dans le fichier",
5221
+ errorParseFailed: "Échec de l'analyse du fichier",
5222
+ errorImportFailed: "Échec de l'importation"
5223
+ }
5224
+ };
5225
+ const deDE = {
5226
+ toolbar: {
5227
+ create: "Neu",
5228
+ import: "Importieren",
5229
+ export: "Exportieren",
5230
+ exportSelected: (count) => `Exportieren (${count})`
5231
+ },
5232
+ rowActions: {
5233
+ view: "Anzeigen",
5234
+ edit: "Bearbeiten",
5235
+ copy: "Kopieren",
5236
+ delete: "Löschen"
5237
+ },
5238
+ viewModal: { title: "Details" },
5239
+ boolean: {
5240
+ true: "Ja",
5241
+ false: "Nein"
5242
+ },
5243
+ formModal: {
5244
+ createTitle: "Neu",
5245
+ editTitle: "Bearbeiten",
5246
+ cancel: "Abbrechen",
5247
+ create: "Erstellen",
5248
+ save: "Speichern",
5249
+ submitting: "Wird verarbeitet..."
5250
+ },
5251
+ deleteModal: {
5252
+ title: "Löschen bestätigen",
5253
+ description: "Diese Aktion kann nicht rückgängig gemacht werden. Möchten Sie diesen Datensatz wirklich löschen?",
5254
+ cancel: "Abbrechen",
5255
+ confirm: "Löschen",
5256
+ confirming: "Wird gelöscht..."
5257
+ },
5258
+ importDialog: {
5259
+ title: "Daten importieren",
5260
+ uploadDescription: "CSV- oder JSON-Datei hochladen, um Daten massenweise zu importieren",
5261
+ previewDescription: (count) => `${count} Datensätze analysiert, bestätigen Sie den Import`,
5262
+ importingDescription: "Daten werden importiert...",
5263
+ doneDescription: "Import abgeschlossen",
5264
+ dragHint: "Datei hierher ziehen oder klicken zum Auswählen",
5265
+ formatHint: "CSV- und JSON-Formate werden unterstützt",
5266
+ downloadTemplate: "CSV-Vorlage herunterladen",
5267
+ moreColumns: (count) => `+${count} Spalten`,
5268
+ previewSummary: (rows, fields, format, previewLimit) => `${rows} Datensätze${previewLimit ? ` (Vorschau der ersten ${previewLimit})` : ""}, ${fields} Felder, Format: ${format.toUpperCase()}`,
5269
+ reselect: "Neu auswählen",
5270
+ confirmImport: "Import bestätigen",
5271
+ importingRows: (count) => `${count} Datensätze werden importiert...`,
5272
+ resultCreated: "Erstellt",
5273
+ resultUpdated: "Aktualisiert",
5274
+ resultSkipped: "Übersprungen",
5275
+ resultFailed: "Fehlgeschlagen",
5276
+ failedRowHeader: "Zeile",
5277
+ failedErrorHeader: "Fehler",
5278
+ close: "Schließen",
5279
+ continueImport: "Weiteren Import starten",
5280
+ errorNoData: "Keine Datenzeilen in der Datei",
5281
+ errorParseFailed: "Datei konnte nicht analysiert werden",
5282
+ errorImportFailed: "Import fehlgeschlagen"
5283
+ }
5284
+ };
5285
+ const esES = {
5286
+ toolbar: {
5287
+ create: "Nuevo",
5288
+ import: "Importar",
5289
+ export: "Exportar",
5290
+ exportSelected: (count) => `Exportar (${count})`
5291
+ },
5292
+ rowActions: {
5293
+ view: "Ver",
5294
+ edit: "Editar",
5295
+ copy: "Copiar",
5296
+ delete: "Eliminar"
5297
+ },
5298
+ viewModal: { title: "Detalles" },
5299
+ boolean: {
5300
+ true: "Sí",
5301
+ false: "No"
5302
+ },
5303
+ formModal: {
5304
+ createTitle: "Nuevo",
5305
+ editTitle: "Editar",
5306
+ cancel: "Cancelar",
5307
+ create: "Crear",
5308
+ save: "Guardar",
5309
+ submitting: "Procesando..."
5310
+ },
5311
+ deleteModal: {
5312
+ title: "Confirmar eliminación",
5313
+ description: "Esta acción no se puede deshacer. ¿Está seguro de que desea eliminar este registro?",
5314
+ cancel: "Cancelar",
5315
+ confirm: "Eliminar",
5316
+ confirming: "Eliminando..."
5317
+ },
5318
+ importDialog: {
5319
+ title: "Importar datos",
5320
+ uploadDescription: "Suba un archivo CSV o JSON para importar datos de forma masiva",
5321
+ previewDescription: (count) => `Se analizaron ${count} registros, confirme para iniciar la importación`,
5322
+ importingDescription: "Importando datos...",
5323
+ doneDescription: "Importación completada",
5324
+ dragHint: "Arrastre el archivo aquí o haga clic para seleccionar",
5325
+ formatHint: "Formatos CSV y JSON compatibles",
5326
+ downloadTemplate: "Descargar plantilla CSV",
5327
+ moreColumns: (count) => `+${count} columnas`,
5328
+ previewSummary: (rows, fields, format, previewLimit) => `${rows} registros${previewLimit ? ` (vista previa de los primeros ${previewLimit})` : ""}, ${fields} campos, formato: ${format.toUpperCase()}`,
5329
+ reselect: "Volver a seleccionar",
5330
+ confirmImport: "Confirmar importación",
5331
+ importingRows: (count) => `Importando ${count} registros...`,
5332
+ resultCreated: "Creados",
5333
+ resultUpdated: "Actualizados",
5334
+ resultSkipped: "Omitidos",
5335
+ resultFailed: "Fallidos",
5336
+ failedRowHeader: "Fila",
5337
+ failedErrorHeader: "Error",
5338
+ close: "Cerrar",
5339
+ continueImport: "Continuar importando",
5340
+ errorNoData: "No se encontraron filas de datos en el archivo",
5341
+ errorParseFailed: "Error al analizar el archivo",
5342
+ errorImportFailed: "Error en la importación"
5343
+ }
5344
+ };
5345
+ const BUILTIN_LOCALES = {
5346
+ "zh-CN": zhCN,
5347
+ "en-US": enUS,
5348
+ "ja-JP": jaJP,
5349
+ "ko-KR": koKR,
5350
+ "fr-FR": frFR,
5351
+ "de-DE": deDE,
5352
+ "es-ES": esES
5353
+ };
5354
+ function deepMerge(target, source) {
5355
+ const result = { ...target };
5356
+ for (const key of Object.keys(source)) {
5357
+ const sv = source[key];
5358
+ const tv = target[key];
5359
+ if (sv !== void 0 && sv !== null && typeof sv === "object" && !Array.isArray(sv) && typeof tv === "object" && tv !== null && !Array.isArray(tv)) result[key] = deepMerge(tv, sv);
5360
+ else if (sv !== void 0) result[key] = sv;
5361
+ }
5362
+ return result;
5363
+ }
5364
+ /**
5365
+ * 解析 locale prop 为完整的 AutoCrudLocale
5366
+ * - string → 内置语言(fallback: zh-CN)
5367
+ * - object → 以 zh-CN 为基础深合并
5368
+ */
5369
+ function resolveLocale(localeProp) {
5370
+ if (!localeProp) return zhCN;
5371
+ if (typeof localeProp === "string") return BUILTIN_LOCALES[localeProp] ?? zhCN;
5372
+ return deepMerge(zhCN, localeProp);
5373
+ }
5374
+
4939
5375
  //#endregion
4940
5376
  //#region src/components/auto-crud/crud-form-modal.tsx
4941
- function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubmit, loading = false, variant = "dialog", overrides, title, labelAlign, labelWidth }) {
4942
- const defaultTitle = mode === "create" ? "新建" : "编辑";
5377
+ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubmit, loading = false, variant = "dialog", overrides, title, locale = zhCN.formModal, labelAlign, labelWidth }) {
5378
+ const defaultTitle = mode === "create" ? locale.createTitle : locale.editTitle;
4943
5379
  const formRef = (0, react.useRef)(null);
4944
5380
  const handleSubmit = async () => {
4945
5381
  await formRef.current?.submit();
@@ -4955,12 +5391,12 @@ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubm
4955
5391
  type: "button",
4956
5392
  variant: "outline",
4957
5393
  onClick: () => onOpenChange(false),
4958
- children: "取消"
5394
+ children: locale.cancel
4959
5395
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
4960
5396
  type: "button",
4961
5397
  onClick: handleSubmit,
4962
5398
  disabled: loading,
4963
- children: loading ? "处理中..." : mode === "create" ? "创建" : "保存"
5399
+ children: loading ? locale.submitting : mode === "create" ? locale.create : locale.save
4964
5400
  })]
4965
5401
  }),
4966
5402
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoForm, {
@@ -4980,7 +5416,7 @@ function CrudFormModal({ open, onOpenChange, mode, schema, initialValues, onSubm
4980
5416
 
4981
5417
  //#endregion
4982
5418
  //#region src/components/auto-crud/import-dialog.tsx
4983
- function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导入数据" }) {
5419
+ function ImportDialog({ open, onOpenChange, onImport, columns = [], title, locale = zhCN.importDialog }) {
4984
5420
  const [step, setStep] = react.useState("upload");
4985
5421
  const [parsedData, setParsedData] = react.useState(null);
4986
5422
  const [error, setError] = react.useState(null);
@@ -5003,13 +5439,13 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5003
5439
  try {
5004
5440
  const data = await parseImportFile(file);
5005
5441
  if (data.rows.length === 0) {
5006
- setError("文件中没有数据行");
5442
+ setError(locale.errorNoData);
5007
5443
  return;
5008
5444
  }
5009
5445
  setParsedData(data);
5010
5446
  setStep("preview");
5011
5447
  } catch (e) {
5012
- setError(e instanceof Error ? e.message : "文件解析失败");
5448
+ setError(e instanceof Error ? e.message : locale.errorParseFailed);
5013
5449
  }
5014
5450
  }, []);
5015
5451
  const handleDrop = react.useCallback((e) => {
@@ -5029,7 +5465,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5029
5465
  setResult(await onImport(parsedData.rows));
5030
5466
  setStep("result");
5031
5467
  } catch (e) {
5032
- setError(e instanceof Error ? e.message : "导入失败");
5468
+ setError(e instanceof Error ? e.message : locale.errorImportFailed);
5033
5469
  setStep("preview");
5034
5470
  }
5035
5471
  }, [parsedData, onImport]);
@@ -5049,11 +5485,11 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5049
5485
  onOpenChange: handleOpenChange,
5050
5486
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogContent, {
5051
5487
  className: "sm:max-w-[600px]",
5052
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children: title }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogDescription, { children: [
5053
- step === "upload" && "上传 CSV 或 JSON 文件以批量导入数据",
5054
- step === "preview" && `已解析 ${parsedData?.rows.length ?? 0} 条数据,确认后开始导入`,
5055
- step === "importing" && "正在导入数据...",
5056
- step === "result" && "导入完成"
5488
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children: title ?? locale.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogDescription, { children: [
5489
+ step === "upload" && locale.uploadDescription,
5490
+ step === "preview" && locale.previewDescription(parsedData?.rows.length ?? 0),
5491
+ step === "importing" && locale.importingDescription,
5492
+ step === "result" && locale.doneDescription
5057
5493
  ] })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5058
5494
  className: "space-y-4",
5059
5495
  children: [
@@ -5084,11 +5520,11 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5084
5520
  }),
5085
5521
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5086
5522
  className: "text-sm text-muted-foreground",
5087
- children: "拖拽文件到此处,或点击选择文件"
5523
+ children: locale.dragHint
5088
5524
  }),
5089
5525
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5090
5526
  className: "text-xs text-muted-foreground/60",
5091
- children: "支持 CSV、JSON 格式"
5527
+ children: locale.formatHint
5092
5528
  })
5093
5529
  ]
5094
5530
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
@@ -5103,7 +5539,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5103
5539
  size: "sm",
5104
5540
  className: "w-full",
5105
5541
  onClick: handleDownloadTemplate,
5106
- children: "下载 CSV 模板"
5542
+ children: locale.downloadTemplate
5107
5543
  })] }),
5108
5544
  step === "preview" && parsedData && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5109
5545
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -5123,13 +5559,9 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5123
5559
  className: "px-3 py-2 text-left font-medium text-muted-foreground",
5124
5560
  children: h
5125
5561
  }, h)),
5126
- parsedData.headers.length > 6 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("th", {
5562
+ parsedData.headers.length > 6 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5127
5563
  className: "px-3 py-2 text-left font-medium text-muted-foreground",
5128
- children: [
5129
- "+",
5130
- parsedData.headers.length - 6,
5131
- " 列"
5132
- ]
5564
+ children: locale.moreColumns(parsedData.headers.length - 6)
5133
5565
  })
5134
5566
  ] })
5135
5567
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: parsedData.rows.slice(0, 10).map((row, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
@@ -5152,40 +5584,27 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5152
5584
  })
5153
5585
  })
5154
5586
  }),
5155
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
5587
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5156
5588
  className: "text-sm text-muted-foreground",
5157
- children: [
5158
- "共 ",
5159
- parsedData.rows.length,
5160
- " 条数据",
5161
- parsedData.rows.length > 10 && "(预览前 10 条)",
5162
- ",",
5163
- parsedData.headers.length,
5164
- " 个字段 ,格式: ",
5165
- parsedData.format.toUpperCase()
5166
- ]
5589
+ children: locale.previewSummary(parsedData.rows.length, parsedData.headers.length, parsedData.format, parsedData.rows.length > 10 ? 10 : void 0)
5167
5590
  }),
5168
5591
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5169
5592
  className: "flex gap-2 justify-end",
5170
5593
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
5171
5594
  variant: "outline",
5172
5595
  onClick: reset,
5173
- children: "重新选择"
5596
+ children: locale.reselect
5174
5597
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
5175
5598
  onClick: handleImport,
5176
- children: "确认导入"
5599
+ children: locale.confirmImport
5177
5600
  })]
5178
5601
  })
5179
5602
  ] }),
5180
5603
  step === "importing" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5181
5604
  className: "flex flex-col items-center gap-4 py-8",
5182
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
5605
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5183
5606
  className: "text-sm text-muted-foreground",
5184
- children: [
5185
- "正在导入 ",
5186
- parsedData?.rows.length ?? 0,
5187
- " 条数据..."
5188
- ]
5607
+ children: locale.importingRows(parsedData?.rows.length ?? 0)
5189
5608
  })]
5190
5609
  }),
5191
5610
  step === "result" && result && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -5200,7 +5619,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5200
5619
  children: result.success
5201
5620
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5202
5621
  className: "text-xs text-green-600/80",
5203
- children: "新建"
5622
+ children: locale.resultCreated
5204
5623
  })]
5205
5624
  }),
5206
5625
  (result.updated ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -5210,7 +5629,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5210
5629
  children: result.updated
5211
5630
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5212
5631
  className: "text-xs text-blue-600/80",
5213
- children: "更新"
5632
+ children: locale.resultUpdated
5214
5633
  })]
5215
5634
  }),
5216
5635
  result.skipped > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -5220,7 +5639,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5220
5639
  children: result.skipped
5221
5640
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5222
5641
  className: "text-xs text-yellow-600/80",
5223
- children: "跳过"
5642
+ children: locale.resultSkipped
5224
5643
  })]
5225
5644
  }),
5226
5645
  result.failed.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -5230,7 +5649,7 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5230
5649
  children: result.failed.length
5231
5650
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5232
5651
  className: "text-xs text-red-600/80",
5233
- children: "验证失败"
5652
+ children: locale.resultFailed
5234
5653
  })]
5235
5654
  })
5236
5655
  ]
@@ -5244,10 +5663,10 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5244
5663
  className: "sticky top-0 bg-red-50 dark:bg-red-950/30",
5245
5664
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5246
5665
  className: "px-3 py-2 text-left font-medium text-red-600",
5247
- children: "行号"
5666
+ children: locale.failedRowHeader
5248
5667
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
5249
5668
  className: "px-3 py-2 text-left font-medium text-red-600",
5250
- children: "错误"
5669
+ children: locale.failedErrorHeader
5251
5670
  })] })
5252
5671
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: result.failed.map((f) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
5253
5672
  className: "border-t border-red-100 dark:border-red-900",
@@ -5267,11 +5686,11 @@ function ImportDialog({ open, onOpenChange, onImport, columns = [], title = "导
5267
5686
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
5268
5687
  variant: "outline",
5269
5688
  onClick: () => handleOpenChange(false),
5270
- children: "关闭"
5689
+ children: locale.close
5271
5690
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
5272
5691
  variant: "outline",
5273
5692
  onClick: reset,
5274
- children: "继续导入"
5693
+ children: locale.continueImport
5275
5694
  })]
5276
5695
  })] }),
5277
5696
  error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -5421,13 +5840,13 @@ function buildBatchUpdateFields(schema, batchFields, fields) {
5421
5840
  /**
5422
5841
  * 渲染字段值
5423
5842
  */
5424
- function renderFieldValue(value, type) {
5843
+ function renderFieldValue(value, type, booleanLocale) {
5425
5844
  if (value === null || value === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5426
5845
  className: "text-muted-foreground",
5427
5846
  children: "-"
5428
5847
  });
5429
5848
  switch (type) {
5430
- case "boolean": return value ? "是" : "否";
5849
+ case "boolean": return value ? booleanLocale.true : booleanLocale.false;
5431
5850
  case "date": return formatDate(value);
5432
5851
  case "enum": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Badge, {
5433
5852
  variant: "outline",
@@ -5450,7 +5869,7 @@ function renderFieldValue(value, type) {
5450
5869
  /**
5451
5870
  * ViewModal 组件 - 详情查看弹窗
5452
5871
  */
5453
- function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldConfig, denyFields }) {
5872
+ function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldConfig, denyFields, locale }) {
5454
5873
  if (!data) return null;
5455
5874
  const shape = schema.shape;
5456
5875
  const denySet = new Set(denyFields ?? []);
@@ -5470,7 +5889,7 @@ function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldCon
5470
5889
  children: label
5471
5890
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", {
5472
5891
  className: "col-span-2 text-sm",
5473
- children: renderFieldValue(value, parsed.type)
5892
+ children: renderFieldValue(value, parsed.type, locale.boolean)
5474
5893
  })]
5475
5894
  }, key);
5476
5895
  })
@@ -5478,23 +5897,89 @@ function ViewModal({ open, onOpenChange, variant, data, schema, fields: fieldCon
5478
5897
  if (variant === "sheet") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Sheet, {
5479
5898
  open,
5480
5899
  onOpenChange,
5481
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.SheetContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetTitle, { children: "详情" }) }), content] })
5900
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.SheetContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.SheetTitle, { children: locale.viewModal.title }) }), content] })
5482
5901
  });
5483
5902
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Dialog, {
5484
5903
  open,
5485
5904
  onOpenChange,
5486
5905
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.DialogContent, {
5487
5906
  className: "max-w-2xl max-h-[80vh] overflow-y-auto",
5488
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children: "详情" }) }), content]
5907
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogHeader, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.DialogTitle, { children: locale.viewModal.title }) }), content]
5489
5908
  })
5490
5909
  });
5491
5910
  }
5911
+ function resolveActions(items, defaults, rowActionsLocale) {
5912
+ const defaultItems = [
5913
+ {
5914
+ label: rowActionsLocale.view,
5915
+ onClick: defaults.openView
5916
+ },
5917
+ ...defaults.openEdit ? [{
5918
+ label: rowActionsLocale.edit,
5919
+ onClick: defaults.openEdit
5920
+ }] : [],
5921
+ ...defaults.copyRow ? [{
5922
+ label: rowActionsLocale.copy,
5923
+ onClick: defaults.copyRow
5924
+ }] : [],
5925
+ ...defaults.openDelete ? [{
5926
+ label: rowActionsLocale.delete,
5927
+ onClick: defaults.openDelete,
5928
+ separator: true,
5929
+ variant: "destructive"
5930
+ }] : []
5931
+ ];
5932
+ if (!items || items.length === 0) return defaultItems;
5933
+ if (!items.some((i) => i.type !== "custom")) {
5934
+ const startItems = items.filter((i) => i.type === "custom" && i.position === "start").map(({ label, onClick, separator, variant }) => ({
5935
+ label,
5936
+ onClick,
5937
+ separator,
5938
+ variant
5939
+ }));
5940
+ const endItems = items.filter((i) => i.type === "custom" && i.position !== "start").map(({ label, onClick, separator, variant }) => ({
5941
+ label,
5942
+ onClick,
5943
+ separator,
5944
+ variant
5945
+ }));
5946
+ return [
5947
+ ...startItems,
5948
+ ...defaultItems,
5949
+ ...endItems
5950
+ ];
5951
+ }
5952
+ const handlerMap = {
5953
+ view: defaults.openView,
5954
+ edit: defaults.openEdit,
5955
+ copy: defaults.copyRow,
5956
+ delete: defaults.openDelete
5957
+ };
5958
+ const variantMap = { delete: "destructive" };
5959
+ return items.flatMap((item) => {
5960
+ if (item.type === "custom") return [{
5961
+ label: item.label,
5962
+ onClick: item.onClick,
5963
+ separator: item.separator,
5964
+ variant: item.variant
5965
+ }];
5966
+ const handler = item.onClick ?? handlerMap[item.type];
5967
+ if (!handler) return [];
5968
+ return [{
5969
+ label: item.label ?? rowActionsLocale[item.type],
5970
+ onClick: handler,
5971
+ separator: item.separator,
5972
+ variant: variantMap[item.type]
5973
+ }];
5974
+ });
5975
+ }
5492
5976
  /**
5493
5977
  * AutoCrudTable 组件
5494
5978
  *
5495
5979
  * 高级 CRUD 表格组件,封装了完整的增删改查流程
5496
5980
  */
5497
- function AutoCrudTable({ title, description, schema, resource, fields, table: tableConfig, form: formConfig, slots, permissions }) {
5981
+ function AutoCrudTable({ title, description, schema, resource, fields, table: tableConfig, form: formConfig, slots, permissions, actions: actionItems, locale: localeProp }) {
5982
+ const locale = resolveLocale(localeProp);
5498
5983
  const can = {
5499
5984
  create: permissions?.can?.create ?? true,
5500
5985
  update: permissions?.can?.update ?? true,
@@ -5587,18 +6072,18 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
5587
6072
  variant: "outline",
5588
6073
  size: "sm",
5589
6074
  onClick: () => setImportOpen(true),
5590
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Download, { className: "mr-2 h-4 w-4" }), "导入"]
6075
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Download, { className: "mr-2 h-4 w-4" }), locale.toolbar.import]
5591
6076
  }),
5592
6077
  canExport && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
5593
6078
  variant: "outline",
5594
6079
  size: "sm",
5595
6080
  onClick: handleExportClick,
5596
6081
  disabled: exporting || selectedCount === 0 && !resource.handlers.export,
5597
- children: [exporting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Upload, { className: "mr-2 h-4 w-4" }), selectedCount > 0 ? `导出(${selectedCount})` : "导出"]
6082
+ children: [exporting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Upload, { className: "mr-2 h-4 w-4" }), selectedCount > 0 ? locale.toolbar.exportSelected(selectedCount) : locale.toolbar.export]
5598
6083
  }),
5599
6084
  can.create && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.Button, {
5600
6085
  onClick: resource.handlers.openCreate,
5601
- children: "新建"
6086
+ children: locale.toolbar.create
5602
6087
  })
5603
6088
  ]
5604
6089
  })]
@@ -5610,12 +6095,12 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
5610
6095
  overrides: tableOverrides,
5611
6096
  exclude: hiddenColumns,
5612
6097
  filterMode: tableConfig?.filterModes,
5613
- actions: {
5614
- onView: resource.handlers.openView,
5615
- onEdit: can.update ? resource.handlers.openEdit : void 0,
5616
- onCopy: can.create ? resource.handlers.copyRow : void 0,
5617
- onDelete: can.delete ? resource.handlers.openDelete : void 0
5618
- },
6098
+ actions: resolveActions(actionItems, {
6099
+ openView: resource.handlers.openView,
6100
+ openEdit: can.update ? resource.handlers.openEdit : void 0,
6101
+ copyRow: can.create ? resource.handlers.copyRow : void 0,
6102
+ openDelete: can.delete ? resource.handlers.openDelete : void 0
6103
+ }, locale.rowActions),
5619
6104
  onDeleteSelected: can.delete ? resource.handlers.deleteMany : void 0,
5620
6105
  onUpdateSelected: can.update ? resource.handlers.updateMany : void 0,
5621
6106
  batchUpdateFields: can.update ? batchFields : void 0,
@@ -5636,7 +6121,8 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
5636
6121
  },
5637
6122
  loading: resource.mutations.isCreating || resource.mutations.isUpdating,
5638
6123
  variant: resource.modal.variant,
5639
- overrides: formOverrides
6124
+ overrides: formOverrides,
6125
+ locale: locale.formModal
5640
6126
  }),
5641
6127
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModal, {
5642
6128
  open: resource.modal.viewOpen,
@@ -5645,22 +6131,24 @@ function AutoCrudTable({ title, description, schema, resource, fields, table: ta
5645
6131
  data: resource.modal.selected,
5646
6132
  schema,
5647
6133
  fields,
5648
- denyFields
6134
+ denyFields,
6135
+ locale
5649
6136
  }),
5650
6137
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialog, {
5651
6138
  open: resource.modal.deleteOpen,
5652
6139
  onOpenChange: (open) => !open && resource.handlers.closeModals(),
5653
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogTitle, { children: "确认删除" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogDescription, { children: "此操作无法撤销。确定要删除这条记录吗?" })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogFooter, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogCancel, { children: "取消" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogAction, {
6140
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogContent, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogHeader, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogTitle, { children: locale.deleteModal.title }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogDescription, { children: locale.deleteModal.description })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.AlertDialogFooter, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogCancel, { children: locale.deleteModal.cancel }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.AlertDialogAction, {
5654
6141
  onClick: resource.handlers.confirmDelete,
5655
6142
  disabled: resource.mutations.isDeleting,
5656
- children: resource.mutations.isDeleting ? "删除中..." : "确认删除"
6143
+ children: resource.mutations.isDeleting ? locale.deleteModal.confirming : locale.deleteModal.confirm
5657
6144
  })] })] })
5658
6145
  }),
5659
6146
  canImport && resource.handlers.import && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImportDialog, {
5660
6147
  open: importOpen,
5661
6148
  onOpenChange: setImportOpen,
5662
6149
  onImport: resource.handlers.import,
5663
- columns: importColumns
6150
+ columns: importColumns,
6151
+ locale: locale.importDialog
5664
6152
  })
5665
6153
  ]
5666
6154
  });
@@ -7056,13 +7544,19 @@ exports.createSelectColumn = createSelectColumn;
7056
7544
  exports.createTRPCDataSource = createTRPCDataSource;
7057
7545
  exports.createTableSchema = createTableSchema;
7058
7546
  exports.dataToCSV = dataToCSV;
7547
+ exports.deDE = deDE;
7059
7548
  exports.downloadCSVTemplate = downloadCSVTemplate;
7549
+ exports.enUS = enUS;
7550
+ exports.esES = esES;
7060
7551
  exports.exportAllToCSV = exportAllToCSV;
7061
7552
  exports.exportTableToCSV = exportTableToCSV;
7062
7553
  exports.formatDate = formatDate;
7554
+ exports.frFR = frFR;
7063
7555
  exports.generateCSVTemplate = generateCSVTemplate;
7064
7556
  exports.getUrlParams = getUrlParams;
7065
7557
  exports.humanize = humanize;
7558
+ exports.jaJP = jaJP;
7559
+ exports.koKR = koKR;
7066
7560
  exports.noopToastAdapter = noopToastAdapter;
7067
7561
  exports.parseAsArrayOf = parseAsArrayOf;
7068
7562
  exports.parseAsInteger = parseAsInteger;
@@ -7072,6 +7566,7 @@ exports.parseCSV = parseCSV;
7072
7566
  exports.parseImportFile = parseImportFile;
7073
7567
  exports.parseJSON = parseJSON;
7074
7568
  exports.parseZodField = parseZodField;
7569
+ exports.resolveLocale = resolveLocale;
7075
7570
  exports.setSearchParams = setSearchParams;
7076
7571
  exports.useAutoCrudResource = useAutoCrudResource;
7077
7572
  exports.useDataTable = useDataTable;
@@ -7079,4 +7574,5 @@ exports.useQueryState = useQueryState;
7079
7574
  exports.useQueryStates = useQueryStates;
7080
7575
  exports.useReadableFilters = useReadableFilters;
7081
7576
  exports.useUrlState = useUrlState;
7082
- exports.useUrlStates = useUrlStates;
7577
+ exports.useUrlStates = useUrlStates;
7578
+ exports.zhCN = zhCN;