@burdenoff/fluidgrids-fe-sdk 2026.804.1 → 2026.804.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.
Files changed (47) hide show
  1. package/dist/ExecutionDetailPage-FF2DYKAZ.js +10 -0
  2. package/dist/{ExecutionDetailPage-FCY3S336.js.map → ExecutionDetailPage-FF2DYKAZ.js.map} +1 -1
  3. package/dist/ExecutionsListPage-NKISRFMA.js +9 -0
  4. package/dist/{ExecutionsListPage-IZJPACQV.js.map → ExecutionsListPage-NKISRFMA.js.map} +1 -1
  5. package/dist/{MissingNodesInstallModal-OT3LJZ4M.js → MissingNodesInstallModal-HA5L3FK2.js} +4 -3
  6. package/dist/MissingNodesInstallModal-HA5L3FK2.js.map +1 -0
  7. package/dist/{TemplateConfigurationModal-7OT6QBEA.js → TemplateConfigurationModal-MXNGZQIC.js} +90 -21
  8. package/dist/TemplateConfigurationModal-MXNGZQIC.js.map +1 -0
  9. package/dist/{TemplateDetailPanel-T3ZHXOHX.js → TemplateDetailPanel-CJ3NPVTP.js} +50 -14
  10. package/dist/TemplateDetailPanel-CJ3NPVTP.js.map +1 -0
  11. package/dist/{WorkflowBuilder-42S2S3PO.js → WorkflowBuilder-ETVB66U6.js} +6 -5
  12. package/dist/{WorkflowBuilder-42S2S3PO.js.map → WorkflowBuilder-ETVB66U6.js.map} +1 -1
  13. package/dist/WorkflowsList-TZAN3YBA.js +11 -0
  14. package/dist/{WorkflowsList-L7EJW54K.js.map → WorkflowsList-TZAN3YBA.js.map} +1 -1
  15. package/dist/{chunk-WAVGHDYH.js → chunk-6PNRM3KQ.js} +469 -114
  16. package/dist/chunk-6PNRM3KQ.js.map +1 -0
  17. package/dist/chunk-7VNIEIR6.js +21 -0
  18. package/dist/chunk-7VNIEIR6.js.map +1 -0
  19. package/dist/{chunk-F5ACDIYR.js → chunk-IWKLEFC7.js} +205 -51
  20. package/dist/chunk-IWKLEFC7.js.map +1 -0
  21. package/dist/{chunk-BRMURCHH.js → chunk-OHGXRM6Z.js} +5 -3
  22. package/dist/chunk-OHGXRM6Z.js.map +1 -0
  23. package/dist/{chunk-CQAHXNT2.js → chunk-SG7Z2IRQ.js} +55 -18
  24. package/dist/chunk-SG7Z2IRQ.js.map +1 -0
  25. package/dist/{chunk-CN3VSAYR.js → chunk-WQ4QNHDN.js} +4600 -1229
  26. package/dist/chunk-WQ4QNHDN.js.map +1 -0
  27. package/dist/{chunk-JPHK5LAL.js → chunk-Y36DJHU3.js} +24 -8
  28. package/dist/chunk-Y36DJHU3.js.map +1 -0
  29. package/dist/{chunk-S7FNNFPU.js → chunk-YJKZSUNC.js} +140 -46
  30. package/dist/chunk-YJKZSUNC.js.map +1 -0
  31. package/dist/index.d.ts +33 -2
  32. package/dist/index.js +637 -174
  33. package/dist/index.js.map +1 -1
  34. package/package.json +1 -1
  35. package/dist/ExecutionDetailPage-FCY3S336.js +0 -9
  36. package/dist/ExecutionsListPage-IZJPACQV.js +0 -8
  37. package/dist/MissingNodesInstallModal-OT3LJZ4M.js.map +0 -1
  38. package/dist/TemplateConfigurationModal-7OT6QBEA.js.map +0 -1
  39. package/dist/TemplateDetailPanel-T3ZHXOHX.js.map +0 -1
  40. package/dist/WorkflowsList-L7EJW54K.js +0 -10
  41. package/dist/chunk-BRMURCHH.js.map +0 -1
  42. package/dist/chunk-CN3VSAYR.js.map +0 -1
  43. package/dist/chunk-CQAHXNT2.js.map +0 -1
  44. package/dist/chunk-F5ACDIYR.js.map +0 -1
  45. package/dist/chunk-JPHK5LAL.js.map +0 -1
  46. package/dist/chunk-S7FNNFPU.js.map +0 -1
  47. package/dist/chunk-WAVGHDYH.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  export { Label } from './chunk-6QCBKN3P.js';
2
- import { FluidGridsProvider, useImportWorkflowTemplate, FlowBuilderPage, useWorkflowTemplates, TemplateCard, Card } from './chunk-CN3VSAYR.js';
3
- export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ConfigSchemaForm, ConnectionFormDialog, ConnectionSelector, EntityTagPicker, FluidGridsProvider, ProviderPicker, WorkflowBuilder as WorkflowBuilderPage, getProviderForm, listCustomBlocks, refetchStoreNodes, registerCustomBlock, resolveUiSpec, stripSubmitActions, useConnection, useConnectionDialog, useConnections, useConnectionsByProvider, useCreateConnection, useFluidGridsContext, useInitiateOAuth, useNodeExecution, useProviderByKey, useProviderCatalog, useProviders } from './chunk-CN3VSAYR.js';
2
+ import { FluidGridsProvider, useImportWorkflowTemplate, FlowBuilderPage, useWorkflowTemplates, TemplateCard, Card } from './chunk-WQ4QNHDN.js';
3
+ export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ConfigSchemaForm, ConnectionFormDialog, ConnectionSelector, EntityTagPicker, FluidGridsProvider, ProviderPicker, WorkflowBuilder as WorkflowBuilderPage, getProviderForm, listCustomBlocks, refetchStoreNodes, registerCustomBlock, resolveUiSpec, stripSubmitActions, useConnection, useConnectionDialog, useConnections, useConnectionsByProvider, useCreateConnection, useFluidGridsContext, useInitiateOAuth, useNodeExecution, useProviderByKey, useProviderCatalog, useProviders } from './chunk-WQ4QNHDN.js';
4
4
  import { Input as Input$1 } from './chunk-P5PKRQAO.js';
5
5
  export { Input } from './chunk-P5PKRQAO.js';
6
- export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './chunk-BRMURCHH.js';
7
- export { ExecutionsListPage } from './chunk-CQAHXNT2.js';
8
- export { ExecutionDetailPage } from './chunk-F5ACDIYR.js';
9
- import './chunk-WAVGHDYH.js';
6
+ export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './chunk-OHGXRM6Z.js';
7
+ export { ExecutionsListPage } from './chunk-SG7Z2IRQ.js';
8
+ export { ExecutionDetailPage } from './chunk-IWKLEFC7.js';
9
+ import './chunk-6PNRM3KQ.js';
10
10
  import { createGlobalStoreClient } from './chunk-BQXHJIER.js';
11
11
  export { createGlobalStoreClient, getGlobalStoreClient, resetGlobalStoreClient, setGlobalStoreClient } from './chunk-BQXHJIER.js';
12
12
  import './chunk-PNOA7CQV.js';
13
- export { WorkflowsList } from './chunk-S7FNNFPU.js';
14
- import { QuotaExhaustedDialog, useFlowStore } from './chunk-JPHK5LAL.js';
15
- export { FLUIDGRIDS_ENTITY_TYPES, tagLabel, useAvailableTags, useCreateTag, useDraftEntityTags, useEntityTags, useFlowStore, useReplaceEntityTags, useSearchTags, useTagEntity, useUntagEntity } from './chunk-JPHK5LAL.js';
13
+ export { WorkflowsList } from './chunk-YJKZSUNC.js';
14
+ import { QuotaExhaustedDialog, useFlowStore } from './chunk-Y36DJHU3.js';
15
+ export { FLUIDGRIDS_ENTITY_TYPES, tagLabel, useAvailableTags, useCreateTag, useDraftEntityTags, useEntityTags, useFlowStore, useReplaceEntityTags, useSearchTags, useTagEntity, useUntagEntity } from './chunk-Y36DJHU3.js';
16
16
  import { useWorkflowDefinition, useWorkflowDefinitions, useDuplicateWorkflow } from './chunk-MH4AHYK3.js';
17
17
  export { useActivateWorkflow, useCreateWorkflow, useCreateWorkflowVersion, useDashboardSummary, useDeactivateWorkflow, useDeleteWorkflow, useDuplicateWorkflow, useLazyWorkflowDefinition, useRestoreWorkflowVersion, useTriggerWorkflow, useUpdateWorkflow, useWorkflowDefinition, useWorkflowDefinitions, useWorkflowRun, useWorkflowRuns, useWorkflowVersions } from './chunk-MH4AHYK3.js';
18
18
  export { ALLOW_ALL_PERMISSIONS, FLUIDGRIDS_PERMISSIONS, FluidGridsPermissionsProvider, SdkPermissionButton, SdkPermissionGate, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, evaluatePermissionCheck, useFluidGridsPermission } from './chunk-UIY2HBWA.js';
@@ -27,6 +27,8 @@ import { Button as Button$1 } from './chunk-DBOMRIP5.js';
27
27
  export { Badge, Button, badgeVariants, buttonVariants } from './chunk-DBOMRIP5.js';
28
28
  import { cn } from './chunk-3ZYUGTIT.js';
29
29
  export { cn } from './chunk-3ZYUGTIT.js';
30
+ import { useTr } from './chunk-7VNIEIR6.js';
31
+ export { ENGLISH_FALLBACK_TRANSLATOR, FluidGridsTranslationProvider, useTr } from './chunk-7VNIEIR6.js';
30
32
  import * as React4 from 'react';
31
33
  import { lazy, Suspense, useState, useEffect, useMemo, useCallback, useRef } from 'react';
32
34
  import { Routes, Route, Navigate, useParams, useNavigate } from 'react-router';
@@ -55,20 +57,20 @@ import * as SwitchPrimitives from '@radix-ui/react-switch';
55
57
  import * as PopoverPrimitive from '@radix-ui/react-popover';
56
58
 
57
59
  var WorkflowsList2 = lazy(
58
- () => import('./WorkflowsList-L7EJW54K.js').then((m) => ({ default: m.WorkflowsList }))
60
+ () => import('./WorkflowsList-TZAN3YBA.js').then((m) => ({ default: m.WorkflowsList }))
59
61
  );
60
62
  var WorkflowBuilder2 = lazy(
61
- () => import('./WorkflowBuilder-42S2S3PO.js').then((m) => ({
63
+ () => import('./WorkflowBuilder-ETVB66U6.js').then((m) => ({
62
64
  default: m.WorkflowBuilder
63
65
  }))
64
66
  );
65
67
  var ExecutionsListPage2 = lazy(
66
- () => import('./ExecutionsListPage-IZJPACQV.js').then((m) => ({
68
+ () => import('./ExecutionsListPage-NKISRFMA.js').then((m) => ({
67
69
  default: m.ExecutionsListPage
68
70
  }))
69
71
  );
70
72
  var ExecutionDetailPage2 = lazy(
71
- () => import('./ExecutionDetailPage-FCY3S336.js').then((m) => ({
73
+ () => import('./ExecutionDetailPage-FF2DYKAZ.js').then((m) => ({
72
74
  default: m.ExecutionDetailPage
73
75
  }))
74
76
  );
@@ -173,20 +175,26 @@ function getNodeColor(type) {
173
175
  return NODE_COLORS[type] ?? NODE_COLORS.default;
174
176
  }
175
177
  function TriggerNode({ data }) {
178
+ const tr = useTr();
176
179
  const label = data.label;
177
180
  return /* @__PURE__ */ jsxs("div", { style: { ...baseNodeStyle, background: getNodeColor("trigger:api") }, children: [
178
- label || "API Trigger",
181
+ label || tr(
182
+ "fluidgrids.components.workflowBuilderCore.triggerNodeLabel",
183
+ "API Trigger"
184
+ ),
179
185
  /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, style: handleStyle })
180
186
  ] });
181
187
  }
182
188
  function EndNode({ data }) {
189
+ const tr = useTr();
183
190
  const label = data.label;
184
191
  return /* @__PURE__ */ jsxs("div", { style: { ...baseNodeStyle, background: getNodeColor("end") }, children: [
185
192
  /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: handleStyle }),
186
- label || "End"
193
+ label || tr("fluidgrids.components.workflowBuilderCore.endNodeLabel", "End")
187
194
  ] });
188
195
  }
189
196
  function ActionNode({ data, type }) {
197
+ const tr = useTr();
190
198
  const label = data.label;
191
199
  const color = getNodeColor(type || "default");
192
200
  return /* @__PURE__ */ jsxs(
@@ -200,7 +208,10 @@ function ActionNode({ data, type }) {
200
208
  },
201
209
  children: [
202
210
  /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: handleStyle }),
203
- label || "Action",
211
+ label || tr(
212
+ "fluidgrids.components.workflowBuilderCore.actionNodeLabel",
213
+ "Action"
214
+ ),
204
215
  /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, style: handleStyle })
205
216
  ]
206
217
  }
@@ -236,6 +247,7 @@ function FlowBuilderInner({
236
247
  className
237
248
  }) {
238
249
  const reactFlowInstance = useReactFlow();
250
+ const tr = useTr();
239
251
  const setWorkflow = useFlowStore((s) => s.actions.setWorkflow);
240
252
  const resetWorkflow = useFlowStore((s) => s.actions.resetWorkflow);
241
253
  const deleteNode = useFlowStore((s) => s.actions.nodes.deleteNode);
@@ -368,7 +380,10 @@ function FlowBuilderInner({
368
380
  className: "font-semibold max-w-[300px]",
369
381
  value: workflowName,
370
382
  onChange: handleNameChange,
371
- placeholder: "Workflow Name",
383
+ placeholder: tr(
384
+ "fluidgrids.components.workflowBuilderCore.workflowNamePlaceholder",
385
+ "Workflow Name"
386
+ ),
372
387
  disabled: readonly
373
388
  }
374
389
  )
@@ -376,11 +391,11 @@ function FlowBuilderInner({
376
391
  !readonly && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
377
392
  /* @__PURE__ */ jsxs(Button$1, { variant: "outline", size: "sm", onClick: handleSave, children: [
378
393
  /* @__PURE__ */ jsx(Save, { className: "size-4 mr-1" }),
379
- "Save"
394
+ tr("fluidgrids.components.workflowBuilderCore.save", "Save")
380
395
  ] }),
381
396
  /* @__PURE__ */ jsxs(Button$1, { size: "sm", onClick: handleExecute, children: [
382
397
  /* @__PURE__ */ jsx(Play, { className: "size-4 mr-1" }),
383
- "Run"
398
+ tr("fluidgrids.components.workflowBuilderCore.run", "Run")
384
399
  ] })
385
400
  ] })
386
401
  ] }),
@@ -412,14 +427,23 @@ function FlowBuilderInner({
412
427
  }
413
428
  ) }),
414
429
  !hideSidebar && !readonly && /* @__PURE__ */ jsxs("div", { className: "w-60 shrink-0 border-l bg-card overflow-y-auto", children: [
415
- /* @__PURE__ */ jsx("div", { className: "p-4 border-b", children: /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", children: "Node Properties" }) }),
430
+ /* @__PURE__ */ jsx("div", { className: "p-4 border-b", children: /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", children: tr(
431
+ "fluidgrids.components.workflowBuilderCore.nodePropertiesHeading",
432
+ "Node Properties"
433
+ ) }) }),
416
434
  selectedNode ? /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-4", children: [
417
435
  /* @__PURE__ */ jsxs("div", { children: [
418
- /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: "Node ID" }),
436
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: tr(
437
+ "fluidgrids.components.workflowBuilderCore.nodeIdLabel",
438
+ "Node ID"
439
+ ) }),
419
440
  /* @__PURE__ */ jsx("code", { className: "block text-xs bg-muted px-2 py-1 rounded font-mono break-all", children: selectedNode.id })
420
441
  ] }),
421
442
  /* @__PURE__ */ jsxs("div", { children: [
422
- /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: "Type" }),
443
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: tr(
444
+ "fluidgrids.components.workflowBuilderCore.nodeTypeLabel",
445
+ "Type"
446
+ ) }),
423
447
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
424
448
  /* @__PURE__ */ jsx(
425
449
  "span",
@@ -436,19 +460,28 @@ function FlowBuilderInner({
436
460
  ] })
437
461
  ] }),
438
462
  /* @__PURE__ */ jsxs("div", { children: [
439
- /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: "Label" }),
463
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: tr(
464
+ "fluidgrids.components.workflowBuilderCore.nodeLabelLabel",
465
+ "Label"
466
+ ) }),
440
467
  /* @__PURE__ */ jsx(
441
468
  Input$1,
442
469
  {
443
470
  value: selectedNode.data?.label ?? "",
444
471
  onChange: (e) => handleSelectedNodeLabelChange(e.target.value),
445
472
  className: "text-sm",
446
- placeholder: "Node label"
473
+ placeholder: tr(
474
+ "fluidgrids.components.workflowBuilderCore.nodeLabelPlaceholder",
475
+ "Node label"
476
+ )
447
477
  }
448
478
  )
449
479
  ] }),
450
480
  /* @__PURE__ */ jsxs("div", { children: [
451
- /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: "Position" }),
481
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: tr(
482
+ "fluidgrids.components.workflowBuilderCore.positionLabel",
483
+ "Position"
484
+ ) }),
452
485
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
453
486
  /* @__PURE__ */ jsxs("div", { children: [
454
487
  "X:",
@@ -463,7 +496,10 @@ function FlowBuilderInner({
463
496
  ] })
464
497
  ] }),
465
498
  /* @__PURE__ */ jsxs("div", { children: [
466
- /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: "Connections" }),
499
+ /* @__PURE__ */ jsx("label", { className: "block text-xs font-medium text-muted-foreground mb-1", children: tr(
500
+ "fluidgrids.components.workflowBuilderCore.connectionsLabel",
501
+ "Connections"
502
+ ) }),
467
503
  /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: (() => {
468
504
  const inbound = edges.filter(
469
505
  (e) => e.target === selectedNode.id
@@ -488,19 +524,34 @@ function FlowBuilderInner({
488
524
  onClick: handleDeleteSelectedNode,
489
525
  children: [
490
526
  /* @__PURE__ */ jsx(Trash2, { className: "size-4 mr-1" }),
491
- "Delete Node"
527
+ tr(
528
+ "fluidgrids.components.workflowBuilderCore.deleteNode",
529
+ "Delete Node"
530
+ )
492
531
  ]
493
532
  }
494
533
  ) })
495
534
  ] }) : /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
496
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Click a node on the canvas to view and edit its properties." }),
497
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-2", children: "Drag nodes from the palette on the left to add them to the workflow." })
535
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tr(
536
+ "fluidgrids.components.workflowBuilderCore.noSelectionHint",
537
+ "Click a node on the canvas to view and edit its properties."
538
+ ) }),
539
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-2", children: tr(
540
+ "fluidgrids.components.workflowBuilderCore.dragPaletteHint",
541
+ "Drag nodes from the palette on the left to add them to the workflow."
542
+ ) })
498
543
  ] })
499
544
  ] })
500
545
  ] }),
501
546
  !hideLogsPanel && /* @__PURE__ */ jsxs("div", { className: "h-32 border-t bg-card p-2", children: [
502
- /* @__PURE__ */ jsx("div", { className: "text-sm font-medium mb-2", children: "Execution Logs" }),
503
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Execution logs will appear here when you run the workflow" })
547
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-medium mb-2", children: tr(
548
+ "fluidgrids.components.workflowBuilderCore.executionLogsHeading",
549
+ "Execution Logs"
550
+ ) }),
551
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tr(
552
+ "fluidgrids.components.workflowBuilderCore.executionLogsEmpty",
553
+ "Execution logs will appear here when you run the workflow"
554
+ ) })
504
555
  ] })
505
556
  ]
506
557
  }
@@ -597,6 +648,7 @@ function extractTemplateGraph(content) {
597
648
  function TemplatePreview() {
598
649
  const { productId } = useParams();
599
650
  const navigate = useNavigate();
651
+ const tr = useTr();
600
652
  const { getTemplateDetail, parseTemplateContent, importTemplate } = useImportWorkflowTemplate();
601
653
  const [workflow, setWorkflow] = useState(null);
602
654
  const [template, setTemplate] = useState(null);
@@ -612,7 +664,12 @@ function TemplatePreview() {
612
664
  let mounted = true;
613
665
  const load = async () => {
614
666
  if (!productId) {
615
- setError("No template specified.");
667
+ setError(
668
+ tr(
669
+ "fluidgrids.pages.templatePreview.errorNoTemplateSpecified",
670
+ "No template specified."
671
+ )
672
+ );
616
673
  setLoading(false);
617
674
  return;
618
675
  }
@@ -620,7 +677,12 @@ function TemplatePreview() {
620
677
  const full = await getTemplateDetail(productId);
621
678
  if (!full) {
622
679
  if (mounted) {
623
- setError("Failed to load template.");
680
+ setError(
681
+ tr(
682
+ "fluidgrids.pages.templatePreview.errorLoadFailed",
683
+ "Failed to load template."
684
+ )
685
+ );
624
686
  setLoading(false);
625
687
  }
626
688
  return;
@@ -631,7 +693,12 @@ function TemplatePreview() {
631
693
  const edges = graph?.edges ?? [];
632
694
  if (!nodes.length) {
633
695
  if (mounted) {
634
- setError("This template has no workflow to preview.");
696
+ setError(
697
+ tr(
698
+ "fluidgrids.pages.templatePreview.errorNoWorkflow",
699
+ "This template has no workflow to preview."
700
+ )
701
+ );
635
702
  setLoading(false);
636
703
  }
637
704
  return;
@@ -642,7 +709,10 @@ function TemplatePreview() {
642
709
  id: productId,
643
710
  workflowKey: productId,
644
711
  version: "preview",
645
- name: full.name ?? "Template",
712
+ name: full.name ?? tr(
713
+ "fluidgrids.pages.templatePreview.fallbackTemplateName",
714
+ "Template"
715
+ ),
646
716
  nodes,
647
717
  edges,
648
718
  sidebar: {
@@ -654,7 +724,12 @@ function TemplatePreview() {
654
724
  }
655
725
  } catch (e) {
656
726
  if (mounted) {
657
- setError(e instanceof Error ? e.message : "Failed to load template.");
727
+ setError(
728
+ e instanceof Error ? e.message : tr(
729
+ "fluidgrids.pages.templatePreview.errorLoadFailed",
730
+ "Failed to load template."
731
+ )
732
+ );
658
733
  setLoading(false);
659
734
  }
660
735
  }
@@ -663,31 +738,58 @@ function TemplatePreview() {
663
738
  return () => {
664
739
  mounted = false;
665
740
  };
666
- }, [productId, getTemplateDetail, parseTemplateContent]);
741
+ }, [productId, getTemplateDetail, parseTemplateContent, tr]);
667
742
  const handleUse = async () => {
668
743
  if (!template) return;
669
744
  setImporting(true);
670
- toast.loading("Importing template...", { id: "tpl-preview-import" });
745
+ toast.loading(
746
+ tr(
747
+ "fluidgrids.pages.templatePreview.importingToast",
748
+ "Importing template..."
749
+ ),
750
+ { id: "tpl-preview-import" }
751
+ );
671
752
  try {
672
753
  const result = await importTemplate(template);
673
754
  toast.dismiss("tpl-preview-import");
674
755
  if (result.success && result.workflow) {
675
- toast.success("Workflow created from template!", {
676
- description: `"${result.workflow.name}" is ready to edit`
677
- });
756
+ toast.success(
757
+ tr(
758
+ "fluidgrids.pages.templatePreview.importSuccessToast",
759
+ "Workflow created from template!"
760
+ ),
761
+ {
762
+ description: `"${result.workflow.name}" is ready to edit`
763
+ }
764
+ );
678
765
  navigate(
679
766
  `${workflowsBase}/workflow/${result.workflow.workflowKey}/${result.workflow.version}`
680
767
  );
681
768
  } else if (isQuotaExhaustedError(result.error?.cause ?? result.error)) {
682
769
  setShowQuotaExhausted(true);
683
770
  } else {
684
- toast.error("Failed to use template", { description: result.message });
771
+ toast.error(
772
+ tr(
773
+ "fluidgrids.pages.templatePreview.importErrorToast",
774
+ "Failed to use template"
775
+ ),
776
+ { description: result.message }
777
+ );
685
778
  }
686
779
  } catch (e) {
687
780
  toast.dismiss("tpl-preview-import");
688
- toast.error("Something went wrong", {
689
- description: e instanceof Error ? e.message : "Failed to import template"
690
- });
781
+ toast.error(
782
+ tr(
783
+ "fluidgrids.pages.templatePreview.genericErrorToast",
784
+ "Something went wrong"
785
+ ),
786
+ {
787
+ description: e instanceof Error ? e.message : tr(
788
+ "fluidgrids.pages.templatePreview.importErrorDescription",
789
+ "Failed to import template"
790
+ )
791
+ }
792
+ );
691
793
  } finally {
692
794
  setImporting(false);
693
795
  }
@@ -702,15 +804,24 @@ function TemplatePreview() {
702
804
  {
703
805
  type: "button",
704
806
  onClick: backToTemplates,
705
- title: "Back to templates",
807
+ title: tr(
808
+ "fluidgrids.pages.templatePreview.backTooltip",
809
+ "Back to templates"
810
+ ),
706
811
  className: "flex size-9 shrink-0 items-center justify-center rounded-md text-card-foreground transition-colors hover:bg-card-foreground/10",
707
812
  children: /* @__PURE__ */ jsx(Icon, { icon: "ion:arrow-back-outline", className: "size-5" })
708
813
  }
709
814
  ),
710
815
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
711
816
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
712
- /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-card-foreground", children: workflow?.name ?? template?.name ?? "Template preview" }),
713
- /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-card-foreground/10 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: "Preview \xB7 read-only" })
817
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-card-foreground", children: workflow?.name ?? template?.name ?? tr(
818
+ "fluidgrids.pages.templatePreview.fallbackHeaderTitle",
819
+ "Template preview"
820
+ ) }),
821
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-card-foreground/10 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: tr(
822
+ "fluidgrids.pages.templatePreview.readOnlyBadge",
823
+ "Preview \xB7 read-only"
824
+ ) })
714
825
  ] }),
715
826
  template?.description ? /* @__PURE__ */ jsx("span", { className: "block truncate text-xs text-muted-foreground", children: template.description }) : null
716
827
  ] })
@@ -729,7 +840,10 @@ function TemplatePreview() {
729
840
  className: "size-4"
730
841
  }
731
842
  ),
732
- "Use this template"
843
+ tr(
844
+ "fluidgrids.pages.templatePreview.useThisTemplate",
845
+ "Use this template"
846
+ )
733
847
  ]
734
848
  }
735
849
  )
@@ -738,12 +852,21 @@ function TemplatePreview() {
738
852
  ErrorBoundary,
739
853
  {
740
854
  fallback: () => /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 p-8 text-center", children: [
741
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Something went wrong rendering this template preview." }),
742
- /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: backToTemplates, children: "Back to templates" })
855
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: tr(
856
+ "fluidgrids.pages.templatePreview.renderErrorMessage",
857
+ "Something went wrong rendering this template preview."
858
+ ) }),
859
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: backToTemplates, children: tr(
860
+ "fluidgrids.pages.templatePreview.backToTemplates",
861
+ "Back to templates"
862
+ ) })
743
863
  ] }),
744
864
  children: loading ? /* @__PURE__ */ jsxs("div", { className: "flex h-full items-center justify-center gap-2 text-sm text-muted-foreground", children: [
745
865
  /* @__PURE__ */ jsx(Icon, { icon: "svg-spinners:ring-resize", className: "size-4" }),
746
- "Loading preview\u2026"
866
+ tr(
867
+ "fluidgrids.pages.templatePreview.loadingPreview",
868
+ "Loading preview\u2026"
869
+ )
747
870
  ] }) : error ? /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-3 p-8 text-center", children: [
748
871
  /* @__PURE__ */ jsx(
749
872
  Icon,
@@ -753,7 +876,10 @@ function TemplatePreview() {
753
876
  }
754
877
  ),
755
878
  /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: error }),
756
- /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: backToTemplates, children: "Back to templates" })
879
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: backToTemplates, children: tr(
880
+ "fluidgrids.pages.templatePreview.backToTemplates",
881
+ "Back to templates"
882
+ ) })
757
883
  ] }) : workflow ? /* @__PURE__ */ jsx(FlowBuilderPage, { workflow, readOnly: true }) : null
758
884
  }
759
885
  ) })
@@ -991,20 +1117,28 @@ function HistoryTableSkeleton() {
991
1117
  )) });
992
1118
  }
993
1119
  function EmptyState() {
1120
+ const tr = useTr();
994
1121
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-20 text-center", children: [
995
1122
  /* @__PURE__ */ jsx("div", { className: "rounded-full bg-background-secondary p-4 mb-4", children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:history", width: 40, className: "text-text-secondary" }) }),
996
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-text-primary mb-2", children: "No version history" }),
997
- /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary max-w-md", children: "Version history will appear here once you create and update workflows." })
1123
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-text-primary mb-2", children: tr("fluidgrids.history.historyPage.emptyTitle", "No version history") }),
1124
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary max-w-md", children: tr(
1125
+ "fluidgrids.history.historyPage.emptyHint",
1126
+ "Version history will appear here once you create and update workflows."
1127
+ ) })
998
1128
  ] });
999
1129
  }
1000
1130
  function ErrorState({
1001
1131
  message,
1002
1132
  onRetry
1003
1133
  }) {
1134
+ const tr = useTr();
1004
1135
  return /* @__PURE__ */ jsxs("div", { className: "p-4 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg", children: [
1005
1136
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[var(--color-status-error-text)]", children: [
1006
1137
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:alert-circle", width: 20 }),
1007
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Error loading history" })
1138
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: tr(
1139
+ "fluidgrids.history.historyPage.errorHeading",
1140
+ "Error loading history"
1141
+ ) })
1008
1142
  ] }),
1009
1143
  /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-[var(--color-status-error-text)]", children: message }),
1010
1144
  /* @__PURE__ */ jsx(
@@ -1014,7 +1148,7 @@ function ErrorState({
1014
1148
  size: "sm",
1015
1149
  onClick: onRetry,
1016
1150
  className: "mt-3 border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] hover:bg-[var(--color-status-error-bg-subtle)]",
1017
- children: "Retry"
1151
+ children: tr("fluidgrids.history.historyPage.errorRetry", "Retry")
1018
1152
  }
1019
1153
  )
1020
1154
  ] });
@@ -1036,6 +1170,7 @@ function StatCard({
1036
1170
  ] });
1037
1171
  }
1038
1172
  function HistoryPage() {
1173
+ const tr = useTr();
1039
1174
  const navigate = useNavigate();
1040
1175
  const [search, setSearch] = useState("");
1041
1176
  const [workflowFilter, setWorkflowFilter] = useState("all");
@@ -1124,17 +1259,23 @@ function HistoryPage() {
1124
1259
  return /* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-6 bg-background-primary min-h-screen", children: [
1125
1260
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6", children: [
1126
1261
  /* @__PURE__ */ jsxs("div", { children: [
1127
- /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: "Version History" }),
1128
- /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: "Track changes and versions across all workflows" })
1262
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: tr("fluidgrids.history.historyPage.title", "Version History") }),
1263
+ /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: tr(
1264
+ "fluidgrids.history.historyPage.subtitle",
1265
+ "Track changes and versions across all workflows"
1266
+ ) })
1129
1267
  ] }),
1130
1268
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1131
1269
  /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: () => refetch(), children: [
1132
1270
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:refresh", className: "mr-2", width: 16 }),
1133
- "Refresh"
1271
+ tr("fluidgrids.history.historyPage.refreshButton", "Refresh")
1134
1272
  ] }),
1135
1273
  /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: () => navigate("../list"), children: [
1136
1274
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:arrow-left", className: "mr-2", width: 16 }),
1137
- "Back to Workflows"
1275
+ tr(
1276
+ "fluidgrids.history.historyPage.backToWorkflowsButton",
1277
+ "Back to Workflows"
1278
+ )
1138
1279
  ] })
1139
1280
  ] })
1140
1281
  ] }),
@@ -1151,7 +1292,10 @@ function HistoryPage() {
1151
1292
  /* @__PURE__ */ jsx(
1152
1293
  Input,
1153
1294
  {
1154
- placeholder: "Search by name, version, key, or author...",
1295
+ placeholder: tr(
1296
+ "fluidgrids.history.historyPage.searchPlaceholder",
1297
+ "Search by name, version, key, or author..."
1298
+ ),
1155
1299
  value: search,
1156
1300
  onChange: (e) => {
1157
1301
  setSearch(e.target.value);
@@ -1170,9 +1314,20 @@ function HistoryPage() {
1170
1314
  setPage(0);
1171
1315
  },
1172
1316
  children: [
1173
- /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[220px] bg-background-secondary border-border-secondary", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "All Workflows" }) }),
1317
+ /* @__PURE__ */ jsx(SelectTrigger, { className: "w-[220px] bg-background-secondary border-border-secondary", children: /* @__PURE__ */ jsx(
1318
+ SelectValue,
1319
+ {
1320
+ placeholder: tr(
1321
+ "fluidgrids.history.historyPage.workflowFilterPlaceholder",
1322
+ "All Workflows"
1323
+ )
1324
+ }
1325
+ ) }),
1174
1326
  /* @__PURE__ */ jsxs(SelectContent, { children: [
1175
- /* @__PURE__ */ jsx(SelectItem, { value: "all", children: "All Workflows" }),
1327
+ /* @__PURE__ */ jsx(SelectItem, { value: "all", children: tr(
1328
+ "fluidgrids.history.historyPage.workflowFilterAllOption",
1329
+ "All Workflows"
1330
+ ) }),
1176
1331
  distinctWorkflows.map((w) => /* @__PURE__ */ jsx(SelectItem, { value: w.workflowKey, children: w.name }, w.workflowKey))
1177
1332
  ] })
1178
1333
  ]
@@ -1180,12 +1335,30 @@ function HistoryPage() {
1180
1335
  )
1181
1336
  ] }),
1182
1337
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-5 gap-3 mb-6", children: [
1183
- /* @__PURE__ */ jsx(StatCard, { label: "Total Versions", value: total || allRows.length }),
1184
- /* @__PURE__ */ jsx(StatCard, { label: "Workflows", value: distinctWorkflows.length }),
1185
1338
  /* @__PURE__ */ jsx(
1186
1339
  StatCard,
1187
1340
  {
1188
- label: "Active",
1341
+ label: tr(
1342
+ "fluidgrids.history.historyPage.statTotalVersions",
1343
+ "Total Versions"
1344
+ ),
1345
+ value: total || allRows.length
1346
+ }
1347
+ ),
1348
+ /* @__PURE__ */ jsx(
1349
+ StatCard,
1350
+ {
1351
+ label: tr(
1352
+ "fluidgrids.history.historyPage.statWorkflows",
1353
+ "Workflows"
1354
+ ),
1355
+ value: distinctWorkflows.length
1356
+ }
1357
+ ),
1358
+ /* @__PURE__ */ jsx(
1359
+ StatCard,
1360
+ {
1361
+ label: tr("fluidgrids.history.historyPage.statActive", "Active"),
1189
1362
  value: countByStatus("ACTIVE"),
1190
1363
  valueClassName: "text-[var(--color-status-success-text)]"
1191
1364
  }
@@ -1193,12 +1366,18 @@ function HistoryPage() {
1193
1366
  /* @__PURE__ */ jsx(
1194
1367
  StatCard,
1195
1368
  {
1196
- label: "Draft",
1369
+ label: tr("fluidgrids.history.historyPage.statDraft", "Draft"),
1197
1370
  value: countByStatus("DRAFT"),
1198
1371
  valueClassName: "text-[var(--color-status-warning-text)]"
1199
1372
  }
1200
1373
  ),
1201
- /* @__PURE__ */ jsx(StatCard, { label: "Archived", value: countByStatus("ARCHIVED") })
1374
+ /* @__PURE__ */ jsx(
1375
+ StatCard,
1376
+ {
1377
+ label: tr("fluidgrids.history.historyPage.statArchived", "Archived"),
1378
+ value: countByStatus("ARCHIVED")
1379
+ }
1380
+ )
1202
1381
  ] }),
1203
1382
  hasMore && /* @__PURE__ */ jsxs("p", { className: "text-xs text-text-secondary mb-4", children: [
1204
1383
  "Showing the ",
@@ -1210,12 +1389,27 @@ function HistoryPage() {
1210
1389
  error && /* @__PURE__ */ jsx("div", { className: "mb-6", children: /* @__PURE__ */ jsx(ErrorState, { message: error.message, onRetry: refetch }) }),
1211
1390
  loading ? /* @__PURE__ */ jsx(HistoryTableSkeleton, {}) : filteredRows.length === 0 ? /* @__PURE__ */ jsx(EmptyState, {}) : /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg border border-border-secondary", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
1212
1391
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b border-border-secondary bg-background-secondary", children: [
1213
- /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: "Workflow Name" }),
1214
- /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: "Version" }),
1215
- /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: "Status" }),
1216
- /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: "Changed By" }),
1217
- /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: "Changed At" }),
1218
- /* @__PURE__ */ jsx("th", { className: "text-right px-4 py-3 font-medium text-text-secondary", children: "Actions" })
1392
+ /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: tr(
1393
+ "fluidgrids.history.historyPage.columnWorkflowName",
1394
+ "Workflow Name"
1395
+ ) }),
1396
+ /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: tr(
1397
+ "fluidgrids.history.historyPage.columnVersion",
1398
+ "Version"
1399
+ ) }),
1400
+ /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: tr("fluidgrids.history.historyPage.columnStatus", "Status") }),
1401
+ /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: tr(
1402
+ "fluidgrids.history.historyPage.columnChangedBy",
1403
+ "Changed By"
1404
+ ) }),
1405
+ /* @__PURE__ */ jsx("th", { className: "text-left px-4 py-3 font-medium text-text-secondary", children: tr(
1406
+ "fluidgrids.history.historyPage.columnChangedAt",
1407
+ "Changed At"
1408
+ ) }),
1409
+ /* @__PURE__ */ jsx("th", { className: "text-right px-4 py-3 font-medium text-text-secondary", children: tr(
1410
+ "fluidgrids.history.historyPage.columnActions",
1411
+ "Actions"
1412
+ ) })
1219
1413
  ] }) }),
1220
1414
  /* @__PURE__ */ jsx("tbody", { children: paginatedRows.map((row) => {
1221
1415
  const statusStyle = STATUS_STYLES[row.status] ?? STATUS_STYLES.DRAFT;
@@ -1268,7 +1462,10 @@ function HistoryPage() {
1268
1462
  children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:open-in-new", width: 16 })
1269
1463
  }
1270
1464
  ) }),
1271
- /* @__PURE__ */ jsx(TooltipContent, { children: "Open in builder" })
1465
+ /* @__PURE__ */ jsx(TooltipContent, { children: tr(
1466
+ "fluidgrids.history.historyPage.openInBuilderTooltip",
1467
+ "Open in builder"
1468
+ ) })
1272
1469
  ] }) }) })
1273
1470
  ]
1274
1471
  },
@@ -1296,7 +1493,10 @@ function HistoryPage() {
1296
1493
  onClick: () => setPage((p) => p - 1),
1297
1494
  children: [
1298
1495
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:chevron-left", width: 16 }),
1299
- "Previous"
1496
+ tr(
1497
+ "fluidgrids.history.historyPage.previousPageButton",
1498
+ "Previous"
1499
+ )
1300
1500
  ]
1301
1501
  }
1302
1502
  ),
@@ -1308,7 +1508,7 @@ function HistoryPage() {
1308
1508
  disabled: page >= totalPages - 1,
1309
1509
  onClick: () => setPage((p) => p + 1),
1310
1510
  children: [
1311
- "Next",
1511
+ tr("fluidgrids.history.historyPage.nextPageButton", "Next"),
1312
1512
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:chevron-right", width: 16 })
1313
1513
  ]
1314
1514
  }
@@ -5447,6 +5647,7 @@ function TemplateSkeleton() {
5447
5647
  return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-52 rounded-lg bg-card-foreground/10" }, i)) });
5448
5648
  }
5449
5649
  function EmptyState2({ hasSearch }) {
5650
+ const tr = useTr();
5450
5651
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-20 text-center", children: [
5451
5652
  /* @__PURE__ */ jsx("div", { className: "rounded-full bg-background-secondary p-4 mb-4", children: /* @__PURE__ */ jsx(
5452
5653
  Icon,
@@ -5456,18 +5657,34 @@ function EmptyState2({ hasSearch }) {
5456
5657
  className: "text-text-secondary"
5457
5658
  }
5458
5659
  ) }),
5459
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-text-primary mb-2", children: hasSearch ? "No matching templates" : "No templates available yet" }),
5460
- /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary max-w-md", children: hasSearch ? "Try adjusting your search or category filter." : "Published workflows will appear here as reusable templates." })
5660
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-text-primary mb-2", children: hasSearch ? tr(
5661
+ "fluidgrids.templates.templatesPage.emptyStateSearchTitle",
5662
+ "No matching templates"
5663
+ ) : tr(
5664
+ "fluidgrids.templates.templatesPage.emptyStateTitle",
5665
+ "No templates available yet"
5666
+ ) }),
5667
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary max-w-md", children: hasSearch ? tr(
5668
+ "fluidgrids.templates.templatesPage.emptyStateSearchHint",
5669
+ "Try adjusting your search or category filter."
5670
+ ) : tr(
5671
+ "fluidgrids.templates.templatesPage.emptyStateHint",
5672
+ "Published workflows will appear here as reusable templates."
5673
+ ) })
5461
5674
  ] });
5462
5675
  }
5463
5676
  function ErrorState2({
5464
5677
  message,
5465
5678
  onRetry
5466
5679
  }) {
5680
+ const tr = useTr();
5467
5681
  return /* @__PURE__ */ jsxs("div", { className: "p-4 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg", children: [
5468
5682
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[var(--color-status-error-text)]", children: [
5469
5683
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:alert-circle", width: 20 }),
5470
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Error loading templates" })
5684
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: tr(
5685
+ "fluidgrids.templates.templatesPage.errorStateTitle",
5686
+ "Error loading templates"
5687
+ ) })
5471
5688
  ] }),
5472
5689
  /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-[var(--color-status-error-text)]", children: message }),
5473
5690
  /* @__PURE__ */ jsx(
@@ -5477,7 +5694,7 @@ function ErrorState2({
5477
5694
  size: "sm",
5478
5695
  onClick: onRetry,
5479
5696
  className: "mt-3 border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] hover:bg-[var(--color-status-error-bg-subtle)]",
5480
- children: "Retry"
5697
+ children: tr("fluidgrids.templates.templatesPage.errorStateRetry", "Retry")
5481
5698
  }
5482
5699
  )
5483
5700
  ] });
@@ -5488,7 +5705,8 @@ function WorkspaceTemplateCard({
5488
5705
  onUseTemplate,
5489
5706
  isLoading
5490
5707
  }) {
5491
- const categoryLabel = CATEGORIES.find((c) => c.value === category)?.label ?? "Workflow";
5708
+ const tr = useTr();
5709
+ const categoryLabel = CATEGORIES.find((c) => c.value === category)?.label ?? tr("fluidgrids.templates.templatesPage.cardDefaultCategory", "Workflow");
5492
5710
  const categoryColor = CATEGORY_COLORS[category] ?? "bg-zinc-500/15 text-zinc-400 border-zinc-500/30";
5493
5711
  return /* @__PURE__ */ jsxs(Card$1, { className: "group border border-border-secondary bg-background-secondary hover:border-border-primary transition-all duration-200 flex flex-col", children: [
5494
5712
  /* @__PURE__ */ jsxs(CardHeader, { className: "flex-1 pb-3", children: [
@@ -5504,7 +5722,10 @@ function WorkspaceTemplateCard({
5504
5722
  /* @__PURE__ */ jsx(Badge, { variant: "outline", className: categoryColor, children: categoryLabel })
5505
5723
  ] }),
5506
5724
  /* @__PURE__ */ jsx("h3", { className: "font-semibold text-text-primary text-base leading-tight mb-1.5 line-clamp-2", children: workflow.name }),
5507
- /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary line-clamp-2 min-h-[2.5rem]", children: workflow.description || "No description provided." })
5725
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary line-clamp-2 min-h-[2.5rem]", children: workflow.description || tr(
5726
+ "fluidgrids.templates.templatesPage.cardNoDescription",
5727
+ "No description provided."
5728
+ ) })
5508
5729
  ] }),
5509
5730
  /* @__PURE__ */ jsx("div", { className: "px-6 pb-5 pt-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
5510
5731
  /* @__PURE__ */ jsxs("span", { className: "text-xs text-text-secondary", children: [
@@ -5528,10 +5749,16 @@ function WorkspaceTemplateCard({
5528
5749
  className: "mr-1.5 animate-spin"
5529
5750
  }
5530
5751
  ),
5531
- "Creating..."
5752
+ tr(
5753
+ "fluidgrids.templates.templatesPage.cardCreating",
5754
+ "Creating..."
5755
+ )
5532
5756
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5533
5757
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:plus", width: 14, className: "mr-1.5" }),
5534
- "Use Template"
5758
+ tr(
5759
+ "fluidgrids.templates.templatesPage.cardUseTemplate",
5760
+ "Use Template"
5761
+ )
5535
5762
  ] })
5536
5763
  }
5537
5764
  )
@@ -5540,6 +5767,7 @@ function WorkspaceTemplateCard({
5540
5767
  }
5541
5768
  function TemplatesPage() {
5542
5769
  const navigate = useNavigate();
5770
+ const tr = useTr();
5543
5771
  const [search, setSearch] = useState("");
5544
5772
  const [activeCategory, setActiveCategory] = useState("all");
5545
5773
  const [duplicatingId, setDuplicatingId] = useState(null);
@@ -5608,13 +5836,21 @@ function TemplatesPage() {
5608
5836
  }
5609
5837
  );
5610
5838
  if (result?.success && result.workflow) {
5611
- toast.success("Workflow created from template");
5839
+ toast.success(
5840
+ tr(
5841
+ "fluidgrids.templates.templatesPage.duplicateSuccessToast",
5842
+ "Workflow created from template"
5843
+ )
5844
+ );
5612
5845
  navigate(
5613
5846
  `../workflow/${result.workflow.workflowKey}/${result.workflow.version}`
5614
5847
  );
5615
5848
  } else {
5616
5849
  toast.error(
5617
- result?.message ?? "Failed to create workflow from template"
5850
+ result?.message ?? tr(
5851
+ "fluidgrids.templates.templatesPage.duplicateErrorToast",
5852
+ "Failed to create workflow from template"
5853
+ )
5618
5854
  );
5619
5855
  }
5620
5856
  } catch (err) {
@@ -5622,66 +5858,120 @@ function TemplatesPage() {
5622
5858
  if (isQuotaExhaustedError(cause) || isQuotaExhaustedError(err)) {
5623
5859
  setShowQuotaExhausted(true);
5624
5860
  } else {
5625
- toast.error("Failed to create workflow from template");
5861
+ toast.error(
5862
+ tr(
5863
+ "fluidgrids.templates.templatesPage.duplicateErrorToast",
5864
+ "Failed to create workflow from template"
5865
+ )
5866
+ );
5626
5867
  console.error("[TemplatesPage] Error duplicating workflow:", err);
5627
5868
  }
5628
5869
  } finally {
5629
5870
  setDuplicatingId(null);
5630
5871
  }
5631
5872
  },
5632
- [duplicateWorkflow, navigate]
5873
+ [duplicateWorkflow, navigate, tr]
5633
5874
  );
5634
5875
  const handleUseStoreTemplate = useCallback(
5635
5876
  async (template) => {
5636
5877
  try {
5637
- toast.loading("Loading template...", { id: "store-template-load" });
5878
+ toast.loading(
5879
+ tr(
5880
+ "fluidgrids.templates.templatesPage.storeLoadingToast",
5881
+ "Loading template..."
5882
+ ),
5883
+ { id: "store-template-load" }
5884
+ );
5638
5885
  const fullTemplate = await getTemplateDetail(template.id);
5639
5886
  toast.dismiss("store-template-load");
5640
5887
  if (!fullTemplate) {
5641
- toast.error("Failed to load template details");
5888
+ toast.error(
5889
+ tr(
5890
+ "fluidgrids.templates.templatesPage.storeLoadDetailErrorToast",
5891
+ "Failed to load template details"
5892
+ )
5893
+ );
5642
5894
  return;
5643
5895
  }
5644
5896
  const content = parseTemplateContent(fullTemplate);
5645
5897
  if (!content) {
5646
- toast.error("Template does not contain valid workflow data");
5898
+ toast.error(
5899
+ tr(
5900
+ "fluidgrids.templates.templatesPage.storeInvalidContentToast",
5901
+ "Template does not contain valid workflow data"
5902
+ )
5903
+ );
5647
5904
  return;
5648
5905
  }
5649
- toast.loading("Importing template...", { id: "store-template-import" });
5906
+ toast.loading(
5907
+ tr(
5908
+ "fluidgrids.templates.templatesPage.storeImportingToast",
5909
+ "Importing template..."
5910
+ ),
5911
+ { id: "store-template-import" }
5912
+ );
5650
5913
  const result = await importTemplate(fullTemplate);
5651
5914
  toast.dismiss("store-template-import");
5652
5915
  if (result.success && result.workflow) {
5653
- toast.success("Workflow created from store template!", {
5654
- description: `"${result.workflow.name}" is ready to edit`
5655
- });
5916
+ toast.success(
5917
+ tr(
5918
+ "fluidgrids.templates.templatesPage.storeImportSuccessToast",
5919
+ "Workflow created from store template!"
5920
+ ),
5921
+ {
5922
+ description: `"${result.workflow.name}" is ready to edit`
5923
+ }
5924
+ );
5656
5925
  navigate(
5657
5926
  `../workflow/${result.workflow.workflowKey}/${result.workflow.version}`
5658
5927
  );
5659
5928
  } else if (isQuotaExhaustedError(result.error?.cause ?? result.error)) {
5660
5929
  setShowQuotaExhausted(true);
5661
5930
  } else {
5662
- toast.error("Failed to import template", {
5663
- description: result.message
5664
- });
5931
+ toast.error(
5932
+ tr(
5933
+ "fluidgrids.templates.templatesPage.storeImportErrorToast",
5934
+ "Failed to import template"
5935
+ ),
5936
+ {
5937
+ description: result.message
5938
+ }
5939
+ );
5665
5940
  }
5666
5941
  } catch (err) {
5667
5942
  toast.dismiss("store-template-load");
5668
5943
  toast.dismiss("store-template-import");
5669
- toast.error("Something went wrong", {
5670
- description: err instanceof Error ? err.message : "Failed to process template"
5671
- });
5944
+ toast.error(
5945
+ tr(
5946
+ "fluidgrids.templates.templatesPage.storeGenericErrorToast",
5947
+ "Something went wrong"
5948
+ ),
5949
+ {
5950
+ description: err instanceof Error ? err.message : tr(
5951
+ "fluidgrids.templates.templatesPage.storeProcessErrorDescription",
5952
+ "Failed to process template"
5953
+ )
5954
+ }
5955
+ );
5672
5956
  }
5673
5957
  },
5674
- [getTemplateDetail, parseTemplateContent, importTemplate, navigate]
5958
+ [getTemplateDetail, parseTemplateContent, importTemplate, navigate, tr]
5675
5959
  );
5676
5960
  return /* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-6 bg-background-primary min-h-screen", children: [
5677
5961
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6", children: [
5678
5962
  /* @__PURE__ */ jsxs("div", { children: [
5679
- /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: "Templates" }),
5680
- /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: "Start quickly with pre-built workflow templates" })
5963
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: tr("fluidgrids.templates.templatesPage.heading", "Templates") }),
5964
+ /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: tr(
5965
+ "fluidgrids.templates.templatesPage.subheading",
5966
+ "Start quickly with pre-built workflow templates"
5967
+ ) })
5681
5968
  ] }),
5682
5969
  /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: () => navigate("../list"), children: [
5683
5970
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:arrow-left", className: "mr-2", width: 16 }),
5684
- "Back to Workflows"
5971
+ tr(
5972
+ "fluidgrids.templates.templatesPage.backToWorkflows",
5973
+ "Back to Workflows"
5974
+ )
5685
5975
  ] })
5686
5976
  ] }),
5687
5977
  /* @__PURE__ */ jsxs("div", { className: "flex gap-1 p-1 bg-background-secondary rounded-lg w-fit mb-6", children: [
@@ -5692,7 +5982,7 @@ function TemplatesPage() {
5692
5982
  className: `px-4 py-2 rounded-md text-sm font-medium transition-colors ${activeSource === "store" ? "bg-background-primary text-text-primary shadow-sm" : "text-text-secondary hover:text-text-primary"}`,
5693
5983
  children: [
5694
5984
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:store", className: "inline mr-1.5", width: 16 }),
5695
- "From Store",
5985
+ tr("fluidgrids.templates.templatesPage.tabFromStore", "From Store"),
5696
5986
  storeTotalCount > 0 && /* @__PURE__ */ jsx("span", { className: "ml-1.5 text-xs bg-primary/10 text-primary px-1.5 py-0.5 rounded-full", children: storeTotalCount })
5697
5987
  ]
5698
5988
  }
@@ -5711,7 +6001,10 @@ function TemplatesPage() {
5711
6001
  width: 16
5712
6002
  }
5713
6003
  ),
5714
- "My Templates"
6004
+ tr(
6005
+ "fluidgrids.templates.templatesPage.tabMyTemplates",
6006
+ "My Templates"
6007
+ )
5715
6008
  ]
5716
6009
  }
5717
6010
  )
@@ -5728,7 +6021,13 @@ function TemplatesPage() {
5728
6021
  /* @__PURE__ */ jsx(
5729
6022
  Input,
5730
6023
  {
5731
- placeholder: activeSource === "workspace" ? "Search workspace templates..." : "Search store templates...",
6024
+ placeholder: activeSource === "workspace" ? tr(
6025
+ "fluidgrids.templates.templatesPage.searchWorkspacePlaceholder",
6026
+ "Search workspace templates..."
6027
+ ) : tr(
6028
+ "fluidgrids.templates.templatesPage.searchStorePlaceholder",
6029
+ "Search store templates..."
6030
+ ),
5732
6031
  value: search,
5733
6032
  onChange: (e) => setSearch(e.target.value),
5734
6033
  className: "pl-10 bg-background-secondary border-border-secondary"
@@ -5808,8 +6107,14 @@ function TemplatesPage() {
5808
6107
  className: "mr-2 animate-spin"
5809
6108
  }
5810
6109
  ),
5811
- "Loading..."
5812
- ] }) : "Load More Templates"
6110
+ tr(
6111
+ "fluidgrids.templates.templatesPage.loadingMore",
6112
+ "Loading..."
6113
+ )
6114
+ ] }) : tr(
6115
+ "fluidgrids.templates.templatesPage.loadMoreTemplates",
6116
+ "Load More Templates"
6117
+ )
5813
6118
  }
5814
6119
  ) })
5815
6120
  ] })
@@ -6061,6 +6366,7 @@ function NodesSkeleton() {
6061
6366
  return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4", children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsx(Skeleton, { className: "h-44 rounded-lg bg-card-foreground/10" }, i)) });
6062
6367
  }
6063
6368
  function EmptyState3({ hasFilters }) {
6369
+ const tr = useTr();
6064
6370
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-20 text-center", children: [
6065
6371
  /* @__PURE__ */ jsx("div", { className: "rounded-full bg-background-secondary p-4 mb-4", children: /* @__PURE__ */ jsx(
6066
6372
  Icon,
@@ -6070,18 +6376,28 @@ function EmptyState3({ hasFilters }) {
6070
6376
  className: "text-text-secondary"
6071
6377
  }
6072
6378
  ) }),
6073
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-text-primary mb-2", children: hasFilters ? "No matching nodes" : "No nodes registered" }),
6074
- /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary max-w-md", children: hasFilters ? "Try adjusting your search or category filter." : "Node endpoint configurations will appear here once registered." })
6379
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-text-primary mb-2", children: hasFilters ? tr(
6380
+ "fluidgrids.nodes.nodesPage.emptyTitleFiltered",
6381
+ "No matching nodes"
6382
+ ) : tr("fluidgrids.nodes.nodesPage.emptyTitle", "No nodes registered") }),
6383
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary max-w-md", children: hasFilters ? tr(
6384
+ "fluidgrids.nodes.nodesPage.emptyHintFiltered",
6385
+ "Try adjusting your search or category filter."
6386
+ ) : tr(
6387
+ "fluidgrids.nodes.nodesPage.emptyHint",
6388
+ "Node endpoint configurations will appear here once registered."
6389
+ ) })
6075
6390
  ] });
6076
6391
  }
6077
6392
  function ErrorState3({
6078
6393
  message,
6079
6394
  onRetry
6080
6395
  }) {
6396
+ const tr = useTr();
6081
6397
  return /* @__PURE__ */ jsxs("div", { className: "p-4 bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)] rounded-lg", children: [
6082
6398
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[var(--color-status-error-text)]", children: [
6083
6399
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:alert-circle", width: 20 }),
6084
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Error loading nodes" })
6400
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: tr("fluidgrids.nodes.nodesPage.errorHeading", "Error loading nodes") })
6085
6401
  ] }),
6086
6402
  /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-[var(--color-status-error-text)]", children: message }),
6087
6403
  /* @__PURE__ */ jsx(
@@ -6091,15 +6407,16 @@ function ErrorState3({
6091
6407
  size: "sm",
6092
6408
  onClick: onRetry,
6093
6409
  className: "mt-3 border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] hover:bg-[var(--color-status-error-bg-subtle)]",
6094
- children: "Retry"
6410
+ children: tr("fluidgrids.nodes.nodesPage.errorRetry", "Retry")
6095
6411
  }
6096
6412
  )
6097
6413
  ] });
6098
6414
  }
6099
6415
  function NodeCard({ node, category }) {
6416
+ const tr = useTr();
6100
6417
  const status = STATUS_STYLES2[node.status] ?? STATUS_STYLES2.AVAILABLE;
6101
6418
  const catColor = CATEGORY_COLORS2[category] ?? "bg-zinc-500/15 text-zinc-400 border-zinc-500/30";
6102
- const catLabel = NODE_CATEGORIES.find((c) => c.value === category)?.label ?? "Node";
6419
+ const catLabel = NODE_CATEGORIES.find((c) => c.value === category)?.label ?? tr("fluidgrids.nodes.nodeCard.categoryFallback", "Node");
6103
6420
  return /* @__PURE__ */ jsxs(Card$1, { className: "border border-border-secondary bg-background-secondary hover:border-border-primary transition-all duration-200 flex flex-col", children: [
6104
6421
  /* @__PURE__ */ jsxs(CardHeader, { className: "flex-1 pb-3", children: [
6105
6422
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2 mb-3", children: [
@@ -6117,7 +6434,10 @@ function NodeCard({ node, category }) {
6117
6434
  ] })
6118
6435
  ] }),
6119
6436
  /* @__PURE__ */ jsx("h3", { className: "font-semibold text-text-primary text-sm leading-tight mb-1 line-clamp-1", children: node.name }),
6120
- /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary line-clamp-2 min-h-[2rem]", children: node.description ?? "No description available." })
6437
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary line-clamp-2 min-h-[2rem]", children: node.description ?? tr(
6438
+ "fluidgrids.nodes.nodeCard.noDescription",
6439
+ "No description available."
6440
+ ) })
6121
6441
  ] }),
6122
6442
  /* @__PURE__ */ jsx("div", { className: "px-6 pb-4 pt-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
6123
6443
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -6129,12 +6449,16 @@ function NodeCard({ node, category }) {
6129
6449
  ] }),
6130
6450
  /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
6131
6451
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("button", { className: "p-1.5 rounded hover:bg-background-tertiary text-text-secondary hover:text-text-primary transition-colors", children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:cog", width: 16 }) }) }),
6132
- /* @__PURE__ */ jsx(TooltipContent, { children: "Configure node" })
6452
+ /* @__PURE__ */ jsx(TooltipContent, { children: tr(
6453
+ "fluidgrids.nodes.nodeCard.configureTooltip",
6454
+ "Configure node"
6455
+ ) })
6133
6456
  ] }) })
6134
6457
  ] }) })
6135
6458
  ] });
6136
6459
  }
6137
6460
  function NodesPage() {
6461
+ const tr = useTr();
6138
6462
  const navigate = useNavigate();
6139
6463
  const [search, setSearch] = useState("");
6140
6464
  const [activeCategory, setActiveCategory] = useState("all");
@@ -6184,17 +6508,23 @@ function NodesPage() {
6184
6508
  return /* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-6 bg-background-primary min-h-screen", children: [
6185
6509
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6", children: [
6186
6510
  /* @__PURE__ */ jsxs("div", { children: [
6187
- /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: "Node Catalog" }),
6188
- /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: "Browse and manage available workflow nodes" })
6511
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: tr("fluidgrids.nodes.nodesPage.title", "Node Catalog") }),
6512
+ /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: tr(
6513
+ "fluidgrids.nodes.nodesPage.subtitle",
6514
+ "Browse and manage available workflow nodes"
6515
+ ) })
6189
6516
  ] }),
6190
6517
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
6191
6518
  /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: () => refetch(), children: [
6192
6519
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:refresh", className: "mr-2", width: 16 }),
6193
- "Refresh"
6520
+ tr("fluidgrids.nodes.nodesPage.refreshButton", "Refresh")
6194
6521
  ] }),
6195
6522
  /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: () => navigate("../list"), children: [
6196
6523
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:arrow-left", className: "mr-2", width: 16 }),
6197
- "Back to Workflows"
6524
+ tr(
6525
+ "fluidgrids.nodes.nodesPage.backToWorkflowsButton",
6526
+ "Back to Workflows"
6527
+ )
6198
6528
  ] })
6199
6529
  ] })
6200
6530
  ] }),
@@ -6209,7 +6539,7 @@ function NodesPage() {
6209
6539
  className: "text-text-secondary"
6210
6540
  }
6211
6541
  ),
6212
- /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: "Total Nodes" })
6542
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: tr("fluidgrids.nodes.nodesPage.statTotal", "Total Nodes") })
6213
6543
  ] }),
6214
6544
  /* @__PURE__ */ jsx("p", { className: "text-xl font-bold text-text-primary mt-1", children: loading ? "\u2014" : stats.total })
6215
6545
  ] }),
@@ -6223,14 +6553,14 @@ function NodesPage() {
6223
6553
  className: "text-emerald-400"
6224
6554
  }
6225
6555
  ),
6226
- /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: "Active" })
6556
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: tr("fluidgrids.nodes.nodesPage.statActive", "Active") })
6227
6557
  ] }),
6228
6558
  /* @__PURE__ */ jsx("p", { className: "text-xl font-bold text-emerald-400 mt-1", children: loading ? "\u2014" : stats.active })
6229
6559
  ] }),
6230
6560
  /* @__PURE__ */ jsxs("div", { className: "p-3 rounded-lg bg-background-secondary border border-border-secondary", children: [
6231
6561
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6232
6562
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:alert", width: 18, className: "text-amber-400" }),
6233
- /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: "Deprecated" })
6563
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: tr("fluidgrids.nodes.nodesPage.statDeprecated", "Deprecated") })
6234
6564
  ] }),
6235
6565
  /* @__PURE__ */ jsx("p", { className: "text-xl font-bold text-amber-400 mt-1", children: loading ? "\u2014" : stats.deprecated })
6236
6566
  ] })
@@ -6247,7 +6577,10 @@ function NodesPage() {
6247
6577
  /* @__PURE__ */ jsx(
6248
6578
  Input,
6249
6579
  {
6250
- placeholder: "Search nodes by name, type, or keyword...",
6580
+ placeholder: tr(
6581
+ "fluidgrids.nodes.nodesPage.searchPlaceholder",
6582
+ "Search nodes by name, type, or keyword..."
6583
+ ),
6251
6584
  value: search,
6252
6585
  onChange: (e) => setSearch(e.target.value),
6253
6586
  className: "pl-10 bg-background-secondary border-border-secondary"
@@ -6314,6 +6647,7 @@ var DEFAULT_SETTINGS = {
6314
6647
  }
6315
6648
  };
6316
6649
  function ReadOnlyBanner() {
6650
+ const tr = useTr();
6317
6651
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-3 rounded-lg bg-amber-500/10 border border-amber-500/30 mb-6", children: [
6318
6652
  /* @__PURE__ */ jsx(
6319
6653
  Icon,
@@ -6323,18 +6657,29 @@ function ReadOnlyBanner() {
6323
6657
  className: "text-amber-400 shrink-0"
6324
6658
  }
6325
6659
  ),
6326
- /* @__PURE__ */ jsx("p", { className: "text-sm text-amber-400", children: "Settings are managed at workspace level. Contact your workspace administrator to change these values." })
6660
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-amber-400", children: tr(
6661
+ "fluidgrids.settings.readOnlyBanner.message",
6662
+ "Settings are managed at workspace level. Contact your workspace administrator to change these values."
6663
+ ) })
6327
6664
  ] });
6328
6665
  }
6329
6666
  function CopyButton({ value, label }) {
6667
+ const tr = useTr();
6330
6668
  const handleCopy = useCallback(async () => {
6331
6669
  try {
6332
6670
  await navigator.clipboard.writeText(value);
6333
- toast.success(`${label} copied to clipboard`);
6671
+ toast.success(
6672
+ `${label} ${tr("fluidgrids.settings.copyButton.copiedToast", "copied to clipboard")}`
6673
+ );
6334
6674
  } catch {
6335
- toast.error("Failed to copy to clipboard");
6675
+ toast.error(
6676
+ tr(
6677
+ "fluidgrids.settings.copyButton.copyFailedToast",
6678
+ "Failed to copy to clipboard"
6679
+ )
6680
+ );
6336
6681
  }
6337
- }, [value, label]);
6682
+ }, [value, label, tr]);
6338
6683
  return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
6339
6684
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6340
6685
  "button",
@@ -6345,7 +6690,8 @@ function CopyButton({ value, label }) {
6345
6690
  }
6346
6691
  ) }),
6347
6692
  /* @__PURE__ */ jsxs(TooltipContent, { children: [
6348
- "Copy ",
6693
+ tr("fluidgrids.settings.copyButton.copyTooltipPrefix", "Copy"),
6694
+ " ",
6349
6695
  label
6350
6696
  ] })
6351
6697
  ] }) });
@@ -6364,6 +6710,7 @@ function SettingRow({
6364
6710
  ] });
6365
6711
  }
6366
6712
  function GeneralTab() {
6713
+ const tr = useTr();
6367
6714
  const settings = DEFAULT_SETTINGS.general;
6368
6715
  return /* @__PURE__ */ jsxs("div", { children: [
6369
6716
  /* @__PURE__ */ jsx(ReadOnlyBanner, {}),
@@ -6371,8 +6718,14 @@ function GeneralTab() {
6371
6718
  /* @__PURE__ */ jsx(
6372
6719
  SettingRow,
6373
6720
  {
6374
- label: "Workspace Name",
6375
- description: "The name of your workspace",
6721
+ label: tr(
6722
+ "fluidgrids.settings.general.workspaceNameLabel",
6723
+ "Workspace Name"
6724
+ ),
6725
+ description: tr(
6726
+ "fluidgrids.settings.general.workspaceNameDescription",
6727
+ "The name of your workspace"
6728
+ ),
6376
6729
  children: /* @__PURE__ */ jsx(
6377
6730
  Input,
6378
6731
  {
@@ -6386,8 +6739,14 @@ function GeneralTab() {
6386
6739
  /* @__PURE__ */ jsx(
6387
6740
  SettingRow,
6388
6741
  {
6389
- label: "Default Workflow Prefix",
6390
- description: "Prefix used when generating new workflow keys",
6742
+ label: tr(
6743
+ "fluidgrids.settings.general.workflowPrefixLabel",
6744
+ "Default Workflow Prefix"
6745
+ ),
6746
+ description: tr(
6747
+ "fluidgrids.settings.general.workflowPrefixDescription",
6748
+ "Prefix used when generating new workflow keys"
6749
+ ),
6391
6750
  children: /* @__PURE__ */ jsx(
6392
6751
  Input,
6393
6752
  {
@@ -6401,8 +6760,14 @@ function GeneralTab() {
6401
6760
  /* @__PURE__ */ jsx(
6402
6761
  SettingRow,
6403
6762
  {
6404
- label: "Auto-save Drafts",
6405
- description: "Automatically save draft workflows while editing",
6763
+ label: tr(
6764
+ "fluidgrids.settings.general.autoSaveDraftsLabel",
6765
+ "Auto-save Drafts"
6766
+ ),
6767
+ description: tr(
6768
+ "fluidgrids.settings.general.autoSaveDraftsDescription",
6769
+ "Automatically save draft workflows while editing"
6770
+ ),
6406
6771
  children: /* @__PURE__ */ jsx(Switch, { checked: settings.autoSaveDrafts, disabled: true })
6407
6772
  }
6408
6773
  )
@@ -6410,6 +6775,7 @@ function GeneralTab() {
6410
6775
  ] });
6411
6776
  }
6412
6777
  function ExecutionTab() {
6778
+ const tr = useTr();
6413
6779
  const settings = DEFAULT_SETTINGS.execution;
6414
6780
  return /* @__PURE__ */ jsxs("div", { children: [
6415
6781
  /* @__PURE__ */ jsx(ReadOnlyBanner, {}),
@@ -6417,8 +6783,14 @@ function ExecutionTab() {
6417
6783
  /* @__PURE__ */ jsx(
6418
6784
  SettingRow,
6419
6785
  {
6420
- label: "Default Timeout",
6421
- description: "Maximum time a workflow execution can run (in seconds)",
6786
+ label: tr(
6787
+ "fluidgrids.settings.execution.defaultTimeoutLabel",
6788
+ "Default Timeout"
6789
+ ),
6790
+ description: tr(
6791
+ "fluidgrids.settings.execution.defaultTimeoutDescription",
6792
+ "Maximum time a workflow execution can run (in seconds)"
6793
+ ),
6422
6794
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6423
6795
  /* @__PURE__ */ jsx(
6424
6796
  Input,
@@ -6428,15 +6800,24 @@ function ExecutionTab() {
6428
6800
  className: "w-[100px] bg-background-secondary border-border-secondary text-text-primary text-right cursor-default"
6429
6801
  }
6430
6802
  ),
6431
- /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: "seconds" })
6803
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: tr(
6804
+ "fluidgrids.settings.execution.defaultTimeoutUnit",
6805
+ "seconds"
6806
+ ) })
6432
6807
  ] })
6433
6808
  }
6434
6809
  ),
6435
6810
  /* @__PURE__ */ jsx(
6436
6811
  SettingRow,
6437
6812
  {
6438
- label: "Max Retries",
6439
- description: "Number of automatic retries on execution failure",
6813
+ label: tr(
6814
+ "fluidgrids.settings.execution.maxRetriesLabel",
6815
+ "Max Retries"
6816
+ ),
6817
+ description: tr(
6818
+ "fluidgrids.settings.execution.maxRetriesDescription",
6819
+ "Number of automatic retries on execution failure"
6820
+ ),
6440
6821
  children: /* @__PURE__ */ jsx(
6441
6822
  Input,
6442
6823
  {
@@ -6450,8 +6831,14 @@ function ExecutionTab() {
6450
6831
  /* @__PURE__ */ jsx(
6451
6832
  SettingRow,
6452
6833
  {
6453
- label: "Retry Delay",
6454
- description: "Delay between retry attempts (in seconds)",
6834
+ label: tr(
6835
+ "fluidgrids.settings.execution.retryDelayLabel",
6836
+ "Retry Delay"
6837
+ ),
6838
+ description: tr(
6839
+ "fluidgrids.settings.execution.retryDelayDescription",
6840
+ "Delay between retry attempts (in seconds)"
6841
+ ),
6455
6842
  children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6456
6843
  /* @__PURE__ */ jsx(
6457
6844
  Input,
@@ -6461,15 +6848,21 @@ function ExecutionTab() {
6461
6848
  className: "w-[100px] bg-background-secondary border-border-secondary text-text-primary text-right cursor-default"
6462
6849
  }
6463
6850
  ),
6464
- /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: "seconds" })
6851
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: tr("fluidgrids.settings.execution.retryDelayUnit", "seconds") })
6465
6852
  ] })
6466
6853
  }
6467
6854
  ),
6468
6855
  /* @__PURE__ */ jsx(
6469
6856
  SettingRow,
6470
6857
  {
6471
- label: "Concurrent Execution Limit",
6472
- description: "Maximum number of workflow executions running simultaneously",
6858
+ label: tr(
6859
+ "fluidgrids.settings.execution.concurrencyLimitLabel",
6860
+ "Concurrent Execution Limit"
6861
+ ),
6862
+ description: tr(
6863
+ "fluidgrids.settings.execution.concurrencyLimitDescription",
6864
+ "Maximum number of workflow executions running simultaneously"
6865
+ ),
6473
6866
  children: /* @__PURE__ */ jsx(
6474
6867
  Input,
6475
6868
  {
@@ -6484,28 +6877,44 @@ function ExecutionTab() {
6484
6877
  ] });
6485
6878
  }
6486
6879
  function NotificationsTab() {
6880
+ const tr = useTr();
6487
6881
  const settings = DEFAULT_SETTINGS.notifications;
6488
6882
  return /* @__PURE__ */ jsxs("div", { children: [
6489
6883
  /* @__PURE__ */ jsx(ReadOnlyBanner, {}),
6490
6884
  /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
6491
6885
  /* @__PURE__ */ jsxs("h3", { className: "text-sm font-semibold text-text-primary flex items-center gap-2 mb-3", children: [
6492
6886
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:email-outline", width: 18 }),
6493
- "Email Notifications"
6887
+ tr(
6888
+ "fluidgrids.settings.notifications.emailSectionTitle",
6889
+ "Email Notifications"
6890
+ )
6494
6891
  ] }),
6495
6892
  /* @__PURE__ */ jsxs("div", { className: "divide-y divide-border-secondary rounded-lg border border-border-secondary bg-background-secondary p-1", children: [
6496
6893
  /* @__PURE__ */ jsx(
6497
6894
  SettingRow,
6498
6895
  {
6499
- label: "On Success",
6500
- description: "Send email when a workflow execution completes successfully",
6896
+ label: tr(
6897
+ "fluidgrids.settings.notifications.emailOnSuccessLabel",
6898
+ "On Success"
6899
+ ),
6900
+ description: tr(
6901
+ "fluidgrids.settings.notifications.emailOnSuccessDescription",
6902
+ "Send email when a workflow execution completes successfully"
6903
+ ),
6501
6904
  children: /* @__PURE__ */ jsx(Switch, { checked: settings.emailOnSuccess, disabled: true })
6502
6905
  }
6503
6906
  ),
6504
6907
  /* @__PURE__ */ jsx(
6505
6908
  SettingRow,
6506
6909
  {
6507
- label: "On Failure",
6508
- description: "Send email when a workflow execution fails",
6910
+ label: tr(
6911
+ "fluidgrids.settings.notifications.emailOnFailureLabel",
6912
+ "On Failure"
6913
+ ),
6914
+ description: tr(
6915
+ "fluidgrids.settings.notifications.emailOnFailureDescription",
6916
+ "Send email when a workflow execution fails"
6917
+ ),
6509
6918
  children: /* @__PURE__ */ jsx(Switch, { checked: settings.emailOnFailure, disabled: true })
6510
6919
  }
6511
6920
  )
@@ -6514,22 +6923,37 @@ function NotificationsTab() {
6514
6923
  /* @__PURE__ */ jsxs("div", { children: [
6515
6924
  /* @__PURE__ */ jsxs("h3", { className: "text-sm font-semibold text-text-primary flex items-center gap-2 mb-3", children: [
6516
6925
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:webhook", width: 18 }),
6517
- "Webhook Notifications"
6926
+ tr(
6927
+ "fluidgrids.settings.notifications.webhookSectionTitle",
6928
+ "Webhook Notifications"
6929
+ )
6518
6930
  ] }),
6519
6931
  /* @__PURE__ */ jsxs("div", { className: "divide-y divide-border-secondary rounded-lg border border-border-secondary bg-background-secondary p-1", children: [
6520
6932
  /* @__PURE__ */ jsx(
6521
6933
  SettingRow,
6522
6934
  {
6523
- label: "On Success",
6524
- description: "Send webhook when a workflow execution completes successfully",
6935
+ label: tr(
6936
+ "fluidgrids.settings.notifications.webhookOnSuccessLabel",
6937
+ "On Success"
6938
+ ),
6939
+ description: tr(
6940
+ "fluidgrids.settings.notifications.webhookOnSuccessDescription",
6941
+ "Send webhook when a workflow execution completes successfully"
6942
+ ),
6525
6943
  children: /* @__PURE__ */ jsx(Switch, { checked: settings.webhookOnSuccess, disabled: true })
6526
6944
  }
6527
6945
  ),
6528
6946
  /* @__PURE__ */ jsx(
6529
6947
  SettingRow,
6530
6948
  {
6531
- label: "On Failure",
6532
- description: "Send webhook when a workflow execution fails",
6949
+ label: tr(
6950
+ "fluidgrids.settings.notifications.webhookOnFailureLabel",
6951
+ "On Failure"
6952
+ ),
6953
+ description: tr(
6954
+ "fluidgrids.settings.notifications.webhookOnFailureDescription",
6955
+ "Send webhook when a workflow execution fails"
6956
+ ),
6533
6957
  children: /* @__PURE__ */ jsx(Switch, { checked: settings.webhookOnFailure, disabled: true })
6534
6958
  }
6535
6959
  )
@@ -6538,17 +6962,33 @@ function NotificationsTab() {
6538
6962
  ] });
6539
6963
  }
6540
6964
  function ApiTab() {
6965
+ const tr = useTr();
6541
6966
  const settings = DEFAULT_SETTINGS.api;
6542
6967
  return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
6543
6968
  /* @__PURE__ */ jsx(Card$1, { className: "border border-border-secondary bg-background-secondary", children: /* @__PURE__ */ jsxs(CardHeader, { className: "pb-3", children: [
6544
6969
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
6545
6970
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:api", width: 20, className: "text-text-secondary" }),
6546
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-text-primary", children: "API Gateway URL" })
6971
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-text-primary", children: tr(
6972
+ "fluidgrids.settings.api.gatewayUrlTitle",
6973
+ "API Gateway URL"
6974
+ ) })
6547
6975
  ] }),
6548
- /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary mb-3", children: "Base URL for workflow API operations. Use this to trigger, list, and manage workflows programmatically." }),
6976
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary mb-3", children: tr(
6977
+ "fluidgrids.settings.api.gatewayUrlDescription",
6978
+ "Base URL for workflow API operations. Use this to trigger, list, and manage workflows programmatically."
6979
+ ) }),
6549
6980
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg bg-background-tertiary px-3 py-2 border border-border-secondary", children: [
6550
6981
  /* @__PURE__ */ jsx("code", { className: "text-sm text-text-primary flex-1 truncate", children: settings.gatewayUrl }),
6551
- /* @__PURE__ */ jsx(CopyButton, { value: settings.gatewayUrl, label: "API Gateway URL" })
6982
+ /* @__PURE__ */ jsx(
6983
+ CopyButton,
6984
+ {
6985
+ value: settings.gatewayUrl,
6986
+ label: tr(
6987
+ "fluidgrids.settings.api.gatewayUrlCopyLabel",
6988
+ "API Gateway URL"
6989
+ )
6990
+ }
6991
+ )
6552
6992
  ] })
6553
6993
  ] }) }),
6554
6994
  /* @__PURE__ */ jsx(Card$1, { className: "border border-border-secondary bg-background-secondary", children: /* @__PURE__ */ jsxs(CardHeader, { className: "pb-3", children: [
@@ -6561,13 +7001,23 @@ function ApiTab() {
6561
7001
  className: "text-text-secondary"
6562
7002
  }
6563
7003
  ),
6564
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-text-primary", children: "Webhook URL Format" })
7004
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-text-primary", children: tr(
7005
+ "fluidgrids.settings.api.webhookUrlTitle",
7006
+ "Webhook URL Format"
7007
+ ) })
6565
7008
  ] }),
6566
7009
  /* @__PURE__ */ jsxs("p", { className: "text-xs text-text-secondary mb-3", children: [
6567
- "URL format for triggering workflows via webhook. Replace",
7010
+ tr(
7011
+ "fluidgrids.settings.api.webhookUrlDescriptionPrefix",
7012
+ "URL format for triggering workflows via webhook. Replace"
7013
+ ),
6568
7014
  " ",
6569
7015
  /* @__PURE__ */ jsx("code", { className: "text-text-primary", children: "{workflowKey}" }),
6570
- " with the actual workflow key."
7016
+ " ",
7017
+ tr(
7018
+ "fluidgrids.settings.api.webhookUrlDescriptionSuffix",
7019
+ "with the actual workflow key."
7020
+ )
6571
7021
  ] }),
6572
7022
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg bg-background-tertiary px-3 py-2 border border-border-secondary", children: [
6573
7023
  /* @__PURE__ */ jsx("code", { className: "text-sm text-text-primary flex-1 truncate", children: settings.webhookUrlFormat }),
@@ -6575,7 +7025,10 @@ function ApiTab() {
6575
7025
  CopyButton,
6576
7026
  {
6577
7027
  value: settings.webhookUrlFormat,
6578
- label: "Webhook URL"
7028
+ label: tr(
7029
+ "fluidgrids.settings.api.webhookUrlCopyLabel",
7030
+ "Webhook URL"
7031
+ )
6579
7032
  }
6580
7033
  )
6581
7034
  ] })
@@ -6590,7 +7043,10 @@ function ApiTab() {
6590
7043
  className: "text-text-secondary"
6591
7044
  }
6592
7045
  ),
6593
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-text-primary", children: "Example: Trigger via cURL" })
7046
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-text-primary", children: tr(
7047
+ "fluidgrids.settings.api.curlExampleTitle",
7048
+ "Example: Trigger via cURL"
7049
+ ) })
6594
7050
  ] }),
6595
7051
  /* @__PURE__ */ jsxs("div", { className: "relative rounded-lg bg-background-tertiary px-3 py-2 border border-border-secondary", children: [
6596
7052
  /* @__PURE__ */ jsx("pre", { className: "text-xs text-text-primary overflow-x-auto whitespace-pre-wrap", children: `curl -X POST "${settings.webhookUrlFormat}" \\
@@ -6604,7 +7060,10 @@ function ApiTab() {
6604
7060
  -H "Content-Type: application/json" \\
6605
7061
  -H "Authorization: Bearer <token>" \\
6606
7062
  -d '{"input": {}}'`,
6607
- label: "cURL command"
7063
+ label: tr(
7064
+ "fluidgrids.settings.api.curlCopyLabel",
7065
+ "cURL command"
7066
+ )
6608
7067
  }
6609
7068
  ) })
6610
7069
  ] })
@@ -6612,36 +7071,40 @@ function ApiTab() {
6612
7071
  ] }) });
6613
7072
  }
6614
7073
  function SettingsPage() {
7074
+ const tr = useTr();
6615
7075
  const navigate = useNavigate();
6616
7076
  const [activeTab, setActiveTab] = useState("general");
6617
7077
  return /* @__PURE__ */ jsxs("div", { className: "p-4 sm:p-6 bg-background-primary min-h-screen", children: [
6618
7078
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6", children: [
6619
7079
  /* @__PURE__ */ jsxs("div", { children: [
6620
- /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: "Settings" }),
6621
- /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: "Configure workflow execution and notification preferences" })
7080
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl sm:text-3xl font-bold text-text-primary", children: tr("fluidgrids.settings.page.title", "Settings") }),
7081
+ /* @__PURE__ */ jsx("p", { className: "text-text-secondary mt-1", children: tr(
7082
+ "fluidgrids.settings.page.subtitle",
7083
+ "Configure workflow execution and notification preferences"
7084
+ ) })
6622
7085
  ] }),
6623
7086
  /* @__PURE__ */ jsxs(Button, { variant: "outline", onClick: () => navigate("../list"), children: [
6624
7087
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:arrow-left", className: "mr-2", width: 16 }),
6625
- "Back to Workflows"
7088
+ tr("fluidgrids.settings.page.backToWorkflows", "Back to Workflows")
6626
7089
  ] })
6627
7090
  ] }),
6628
7091
  /* @__PURE__ */ jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "w-full", children: [
6629
7092
  /* @__PURE__ */ jsxs(TabsList, { className: "bg-background-secondary border border-border-secondary mb-6", children: [
6630
7093
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "general", className: "gap-1.5", children: [
6631
7094
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:cog", width: 16 }),
6632
- "General"
7095
+ tr("fluidgrids.settings.page.generalTab", "General")
6633
7096
  ] }),
6634
7097
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "execution", className: "gap-1.5", children: [
6635
7098
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:play-circle", width: 16 }),
6636
- "Execution"
7099
+ tr("fluidgrids.settings.page.executionTab", "Execution")
6637
7100
  ] }),
6638
7101
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "notifications", className: "gap-1.5", children: [
6639
7102
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:bell-outline", width: 16 }),
6640
- "Notifications"
7103
+ tr("fluidgrids.settings.page.notificationsTab", "Notifications")
6641
7104
  ] }),
6642
7105
  /* @__PURE__ */ jsxs(TabsTrigger, { value: "api", className: "gap-1.5", children: [
6643
7106
  /* @__PURE__ */ jsx(Icon, { icon: "mdi:api", width: 16 }),
6644
- "API"
7107
+ tr("fluidgrids.settings.page.apiTab", "API")
6645
7108
  ] })
6646
7109
  ] }),
6647
7110
  /* @__PURE__ */ jsx(TabsContent, { value: "general", children: /* @__PURE__ */ jsx(GeneralTab, {}) }),