strapi-plugin-magic-sessionmanager 4.0.1 → 4.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.
Files changed (57) hide show
  1. package/README.md +2 -2
  2. package/admin/src/components/OnlineUsersWidget.jsx +11 -7
  3. package/admin/src/components/SessionDetailModal.jsx +42 -38
  4. package/admin/src/components/SessionInfoPanel.jsx +29 -20
  5. package/admin/src/index.js +9 -0
  6. package/admin/src/pages/HomePage.jsx +128 -161
  7. package/admin/src/pages/License.jsx +3 -3
  8. package/admin/src/pages/Settings.jsx +139 -135
  9. package/admin/src/pages/UpgradePage.jsx +448 -0
  10. package/admin/src/pluginId.js +1 -0
  11. package/admin/src/translations/de.json +294 -15
  12. package/admin/src/translations/en.json +293 -14
  13. package/admin/src/translations/es.json +284 -18
  14. package/admin/src/translations/fr.json +284 -18
  15. package/admin/src/translations/pt.json +284 -18
  16. package/admin/src/utils/theme.js +85 -0
  17. package/dist/_chunks/{Analytics-Dv9f_0eZ.mjs → Analytics-DTE_zmRV.mjs} +2 -2
  18. package/dist/_chunks/{Analytics-BBdv1I5y.js → Analytics-lw_JaOVy.js} +2 -2
  19. package/dist/_chunks/{App-CJaZPNjt.js → App-DDKYCjKw.js} +216 -206
  20. package/dist/_chunks/{App-CIQ-7sa7.mjs → App-DJW1ZNl5.mjs} +216 -206
  21. package/dist/_chunks/{License-nrmFxoBm.mjs → License-DaOFuImm.mjs} +4 -8
  22. package/dist/_chunks/{License-D24rgaZQ.js → License-Tk-6UfPl.js} +4 -8
  23. package/dist/_chunks/{OnlineUsersWidget-B8JS1xZu.js → OnlineUsersWidget-C1qTpsws.js} +11 -7
  24. package/dist/_chunks/{OnlineUsersWidget-ArMl0nen.mjs → OnlineUsersWidget-CADphbXG.mjs} +11 -7
  25. package/dist/_chunks/{Settings-D5dLEGc_.mjs → Settings-C9xvckgq.mjs} +191 -179
  26. package/dist/_chunks/{Settings-CqxgjU0y.js → Settings-DyEAuTNQ.js} +191 -179
  27. package/dist/_chunks/UpgradePage-Dssk8A0Z.js +354 -0
  28. package/dist/_chunks/UpgradePage-cINvE9zY.mjs +352 -0
  29. package/dist/_chunks/de-CDA1V0rF.mjs +292 -0
  30. package/dist/_chunks/de-I-Q-pWqu.js +292 -0
  31. package/dist/_chunks/en-Bd7_h-4e.js +292 -0
  32. package/dist/_chunks/en-DzmOCyzQ.mjs +292 -0
  33. package/dist/_chunks/es-BcAx18XG.js +277 -0
  34. package/dist/_chunks/es-Cx-SN6qV.mjs +277 -0
  35. package/dist/_chunks/fr-DCzYMuJ-.js +277 -0
  36. package/dist/_chunks/fr-DXlXE5Eo.mjs +277 -0
  37. package/dist/_chunks/{index-WH04CS1c.js → index-CWcvrfXc.js} +45 -42
  38. package/dist/_chunks/{index-Duk1_Wrz.mjs → index-DQO9bNP7.mjs} +45 -42
  39. package/dist/_chunks/pt-21-MAb72.js +277 -0
  40. package/dist/_chunks/pt-zsdTSjba.mjs +277 -0
  41. package/dist/_chunks/{useLicense-BwOlCyhc.js → useLicense-DtvJOszr.js} +1 -1
  42. package/dist/_chunks/{useLicense-Ce8GaxB0.mjs → useLicense-DxbD4Wf8.mjs} +1 -1
  43. package/dist/admin/index.js +1 -1
  44. package/dist/admin/index.mjs +1 -1
  45. package/dist/server/index.js +1 -1
  46. package/dist/server/index.mjs +1 -1
  47. package/package.json +1 -1
  48. package/dist/_chunks/de-BxFx1pwE.js +0 -23
  49. package/dist/_chunks/de-CdO3s01z.mjs +0 -23
  50. package/dist/_chunks/en-CsPpPJL3.mjs +0 -23
  51. package/dist/_chunks/en-RqmpDHdS.js +0 -23
  52. package/dist/_chunks/es-CuLHazN1.js +0 -23
  53. package/dist/_chunks/es-Dkmjhy9c.mjs +0 -23
  54. package/dist/_chunks/fr-BAJp2yhI.js +0 -23
  55. package/dist/_chunks/fr-Bssg_3UF.mjs +0 -23
  56. package/dist/_chunks/pt-BAP9cKs3.js +0 -23
  57. package/dist/_chunks/pt-BVNoNcuY.mjs +0 -23
@@ -2,12 +2,13 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const react = require("react");
5
+ const reactIntl = require("react-intl");
5
6
  const designSystem = require("@strapi/design-system");
6
7
  const admin = require("@strapi/strapi/admin");
7
8
  const icons = require("@strapi/icons");
8
9
  const styled = require("styled-components");
9
- const index = require("./index-WH04CS1c.js");
10
- const useLicense = require("./useLicense-BwOlCyhc.js");
10
+ const index = require("./index-CWcvrfXc.js");
11
+ const useLicense = require("./useLicense-DtvJOszr.js");
11
12
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
13
  const styled__default = /* @__PURE__ */ _interopDefault(styled);
13
14
  const theme = {
@@ -17,7 +18,6 @@ const theme = {
17
18
  danger: { 600: "#DC2626" },
18
19
  neutral: { 0: "#FFFFFF", 200: "#E5E7EB", 400: "#9CA3AF", 700: "#374151" }
19
20
  },
20
- shadows: { sm: "0 1px 3px rgba(0,0,0,0.1)" },
21
21
  borderRadius: { md: "8px", lg: "12px" }
22
22
  };
23
23
  const fadeIn = styled.keyframes`
@@ -37,9 +37,9 @@ const StickySaveBar = styled__default.default(designSystem.Box)`
37
37
  position: sticky;
38
38
  top: 0;
39
39
  z-index: 10;
40
- background: white;
41
- border-bottom: 1px solid ${theme.colors.neutral[200]};
42
- box-shadow: ${theme.shadows.sm};
40
+ background: ${(props) => props.theme.colors.neutral0};
41
+ border-bottom: 1px solid ${(props) => props.theme.colors.neutral200};
42
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
43
43
  `;
44
44
  const ToggleCard = styled__default.default(designSystem.Box)`
45
45
  background: ${(props) => props.$active ? "linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%)" : "linear-gradient(135deg, #fafafa 0%, #f3f4f6 100%)"};
@@ -337,9 +337,11 @@ const generateSecureKey = () => {
337
337
  return key;
338
338
  };
339
339
  const SettingsPage = () => {
340
+ const { formatMessage } = reactIntl.useIntl();
340
341
  const { get, post, put } = admin.useFetchClient();
341
342
  const { toggleNotification } = admin.useNotification();
342
343
  const { isPremium, isAdvanced, isEnterprise } = useLicense.useLicense();
344
+ const t = (id, defaultMessage, values) => formatMessage({ id: index.getTranslation(id), defaultMessage }, values);
343
345
  const [loading, setLoading] = react.useState(true);
344
346
  const [saving, setSaving] = react.useState(false);
345
347
  const [hasChanges, setHasChanges] = react.useState(false);
@@ -405,7 +407,7 @@ const SettingsPage = () => {
405
407
  console.error("[Settings] Error loading from backend:", err);
406
408
  toggleNotification({
407
409
  type: "warning",
408
- message: "Could not load settings from server. Using defaults."
410
+ message: t("notifications.warning.settingsLoad", "Could not load settings from server. Using defaults.")
409
411
  });
410
412
  setSettings((prev) => ({ ...prev, emailTemplates: getDefaultTemplates() }));
411
413
  } finally {
@@ -423,7 +425,7 @@ const SettingsPage = () => {
423
425
  if (response?.data?.success) {
424
426
  toggleNotification({
425
427
  type: "success",
426
- message: "Settings saved successfully to database!"
428
+ message: t("notifications.success.saved", "Settings saved successfully to database!")
427
429
  });
428
430
  setHasChanges(false);
429
431
  try {
@@ -438,7 +440,7 @@ const SettingsPage = () => {
438
440
  console.error("[Settings] Error saving:", err);
439
441
  toggleNotification({
440
442
  type: "danger",
441
- message: "Failed to save settings to server"
443
+ message: t("notifications.error.save", "Failed to save settings to server")
442
444
  });
443
445
  } finally {
444
446
  setSaving(false);
@@ -449,7 +451,7 @@ const SettingsPage = () => {
449
451
  setHasChanges(false);
450
452
  };
451
453
  const handleCleanInactive = async () => {
452
- if (!confirm("[WARNING] This will permanently delete ALL inactive sessions.\n\nContinue?")) {
454
+ if (!confirm(t("settings.general.danger.confirm", "[WARNING] This will permanently delete ALL inactive sessions.\n\nContinue?"))) {
453
455
  return;
454
456
  }
455
457
  setCleaning(true);
@@ -457,28 +459,31 @@ const SettingsPage = () => {
457
459
  const { data } = await post(`/${index.pluginId}/sessions/clean-inactive`);
458
460
  toggleNotification({
459
461
  type: "success",
460
- message: `Successfully deleted ${data.deletedCount} inactive sessions!`
462
+ message: t("notifications.success.cleaned", "Successfully deleted {count} inactive sessions!", { count: data.deletedCount })
461
463
  });
462
464
  } catch (err) {
463
465
  toggleNotification({
464
466
  type: "danger",
465
- message: "Failed to delete inactive sessions"
467
+ message: t("notifications.error.clean", "Failed to delete inactive sessions")
466
468
  });
467
469
  } finally {
468
470
  setCleaning(false);
469
471
  }
470
472
  };
471
473
  if (loading) {
472
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { children: "Loading settings..." }) });
474
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { children: t("common.loading", "Loading...") }) });
473
475
  }
474
476
  return /* @__PURE__ */ jsxRuntime.jsxs(Container, { children: [
475
477
  /* @__PURE__ */ jsxRuntime.jsx(StickySaveBar, { paddingTop: 5, paddingBottom: 5, paddingLeft: 6, paddingRight: 6, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
476
478
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 1, alignItems: "flex-start", children: [
477
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", fontWeight: "bold", style: { fontSize: "24px" }, children: "⚙️ Session Manager Settings" }),
478
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", children: "Configure session tracking, security, and email notifications" })
479
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "alpha", fontWeight: "bold", style: { fontSize: "24px" }, children: [
480
+ "⚙️ ",
481
+ t("settings.title", "Session Manager Settings")
482
+ ] }),
483
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", children: t("settings.subtitle", "Configure session tracking, security, and email notifications") })
479
484
  ] }),
480
485
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
481
- hasChanges && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleReset, variant: "tertiary", size: "L", children: "Reset" }),
486
+ hasChanges && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleReset, variant: "tertiary", size: "L", children: t("settings.reset", "Reset") }),
482
487
  /* @__PURE__ */ jsxRuntime.jsx(
483
488
  designSystem.Button,
484
489
  {
@@ -506,7 +511,7 @@ const SettingsPage = () => {
506
511
  e.currentTarget.style.transform = "translateY(0)";
507
512
  e.currentTarget.style.boxShadow = hasChanges && !saving ? "0 4px 12px rgba(102, 126, 234, 0.4)" : "none";
508
513
  },
509
- children: saving ? "Saving..." : hasChanges ? "Save Changes" : "No Changes"
514
+ children: saving ? t("settings.saving", "Saving...") : hasChanges ? t("settings.save", "Save Changes") : t("settings.noChanges", "No Changes")
510
515
  }
511
516
  )
512
517
  ] })
@@ -515,19 +520,22 @@ const SettingsPage = () => {
515
520
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "primary50", hasRadius: true, style: { marginBottom: "24px", border: "1px solid #bae6fd" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "center", children: [
516
521
  /* @__PURE__ */ jsxRuntime.jsx(icons.Information, { style: { width: "20px", height: "20px", color: "#0284C7" } }),
517
522
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
518
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "primary700", style: { marginBottom: "4px" }, children: "Current License Status" }),
523
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "primary700", style: { marginBottom: "4px" }, children: t("settings.license.title", "Current License Status") }),
519
524
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, children: [
520
525
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: isPremium ? "success100" : "neutral100", textColor: isPremium ? "success700" : "neutral600", children: [
521
526
  isPremium ? "✓" : "✗",
522
- " Premium"
527
+ " ",
528
+ t("settings.license.premium", "Premium")
523
529
  ] }),
524
530
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: isAdvanced ? "primary100" : "neutral100", textColor: isAdvanced ? "primary700" : "neutral600", children: [
525
531
  isAdvanced ? "✓" : "✗",
526
- " Advanced"
532
+ " ",
533
+ t("settings.license.advanced", "Advanced")
527
534
  ] }),
528
535
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Badge, { backgroundColor: isEnterprise ? "secondary100" : "neutral100", textColor: isEnterprise ? "secondary700" : "neutral600", children: [
529
536
  isEnterprise ? "✓" : "✗",
530
- " Enterprise"
537
+ " ",
538
+ t("settings.license.enterprise", "Enterprise")
531
539
  ] })
532
540
  ] })
533
541
  ] })
@@ -538,114 +546,99 @@ const SettingsPage = () => {
538
546
  designSystem.Accordion.Trigger,
539
547
  {
540
548
  icon: icons.Cog,
541
- description: "Basic session tracking configuration",
542
- children: "General Settings"
549
+ description: t("settings.general.description", "Basic session tracking configuration"),
550
+ children: t("settings.general.title", "General Settings")
543
551
  }
544
552
  ) }),
545
553
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, children: [
546
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: "SESSION TIMEOUT" }),
554
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: t("settings.general.timeout.title", "SESSION TIMEOUT") }),
547
555
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 6, style: { marginBottom: "32px" }, children: [
548
556
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
549
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: "Inactivity Timeout" }),
557
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: t("settings.general.timeout.inactivity", "Inactivity Timeout") }),
550
558
  /* @__PURE__ */ jsxRuntime.jsxs(
551
559
  designSystem.SingleSelect,
552
560
  {
553
561
  value: String(settings.inactivityTimeout),
554
562
  onChange: (value) => handleChange("inactivityTimeout", parseInt(value)),
555
563
  children: [
556
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "5", children: "5 minutes (Very Strict)" }),
557
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10", children: "10 minutes (Strict)" }),
558
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "15", children: "15 minutes (Recommended)" }),
559
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: "30 minutes (Moderate)" }),
560
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: "1 hour (Relaxed)" }),
561
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "120", children: "2 hours (Very Relaxed)" })
564
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "5", children: t("settings.general.timeout.5min", "5 minutes (Very Strict)") }),
565
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10", children: t("settings.general.timeout.10min", "10 minutes (Strict)") }),
566
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "15", children: t("settings.general.timeout.15min", "15 minutes (Recommended)") }),
567
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: t("settings.general.timeout.30min", "30 minutes (Moderate)") }),
568
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: t("settings.general.timeout.1hour", "1 hour (Relaxed)") }),
569
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "120", children: t("settings.general.timeout.2hours", "2 hours (Very Relaxed)") })
562
570
  ]
563
571
  }
564
572
  ),
565
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: [
566
- "Sessions inactive for more than ",
567
- settings.inactivityTimeout,
568
- " minutes will be marked as offline"
569
- ] })
573
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: t("settings.general.timeout.inactivityHint", "Sessions inactive for more than {minutes} minutes will be marked as offline", { minutes: settings.inactivityTimeout }) })
570
574
  ] }) }),
571
575
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
572
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: "Last Seen Rate Limit" }),
576
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: t("settings.general.rateLimit.title", "Last Seen Rate Limit") }),
573
577
  /* @__PURE__ */ jsxRuntime.jsxs(
574
578
  designSystem.SingleSelect,
575
579
  {
576
580
  value: String(settings.lastSeenRateLimit),
577
581
  onChange: (value) => handleChange("lastSeenRateLimit", parseInt(value)),
578
582
  children: [
579
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10", children: "10 seconds" }),
580
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: "30 seconds (Recommended)" }),
581
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: "1 minute" }),
582
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "120", children: "2 minutes" }),
583
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "300", children: "5 minutes" })
583
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "10", children: t("settings.general.rateLimit.10sec", "10 seconds") }),
584
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: t("settings.general.rateLimit.30sec", "30 seconds (Recommended)") }),
585
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: t("settings.general.rateLimit.1min", "1 minute") }),
586
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "120", children: t("settings.general.rateLimit.2min", "2 minutes") }),
587
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "300", children: t("settings.general.rateLimit.5min", "5 minutes") })
584
588
  ]
585
589
  }
586
590
  ),
587
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: [
588
- "Prevents excessive database writes. Updates throttled to once every ",
589
- settings.lastSeenRateLimit,
590
- " seconds"
591
- ] })
591
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: t("settings.general.rateLimit.hint", "Prevents excessive database writes. Updates throttled to once every {seconds} seconds", { seconds: settings.lastSeenRateLimit }) })
592
592
  ] }) })
593
593
  ] }),
594
594
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, { style: { marginBottom: "24px" } }),
595
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: "🧹 AUTO-CLEANUP & RETENTION" }),
595
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: [
596
+ "🧹 ",
597
+ t("settings.general.cleanup.title", "AUTO-CLEANUP & RETENTION")
598
+ ] }),
596
599
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 6, children: [
597
600
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
598
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: "Cleanup Interval" }),
601
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: t("settings.general.cleanup.interval", "Cleanup Interval") }),
599
602
  /* @__PURE__ */ jsxRuntime.jsxs(
600
603
  designSystem.SingleSelect,
601
604
  {
602
605
  value: String(settings.cleanupInterval),
603
606
  onChange: (value) => handleChange("cleanupInterval", parseInt(value)),
604
607
  children: [
605
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "15", children: "15 minutes" }),
606
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: "30 minutes (Recommended)" }),
607
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: "1 hour" }),
608
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "120", children: "2 hours" })
608
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "15", children: t("settings.general.cleanup.15min", "15 minutes") }),
609
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: t("settings.general.cleanup.30min", "30 minutes (Recommended)") }),
610
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: t("settings.general.cleanup.1hour", "1 hour") }),
611
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "120", children: t("settings.general.cleanup.2hours", "2 hours") })
609
612
  ]
610
613
  }
611
614
  ),
612
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: [
613
- "Inactive sessions are automatically cleaned every ",
614
- settings.cleanupInterval,
615
- " minutes"
616
- ] })
615
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: t("settings.general.cleanup.intervalHint", "Inactive sessions are automatically cleaned every {minutes} minutes", { minutes: settings.cleanupInterval }) })
617
616
  ] }) }),
618
617
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
619
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: "Retention Period" }),
618
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: t("settings.general.retention.title", "Retention Period") }),
620
619
  /* @__PURE__ */ jsxRuntime.jsxs(
621
620
  designSystem.SingleSelect,
622
621
  {
623
622
  value: String(settings.retentionDays),
624
623
  onChange: (value) => handleChange("retentionDays", parseInt(value)),
625
624
  children: [
626
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "7", children: "7 days" }),
627
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: "30 days" }),
628
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: "60 days" }),
629
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "90", children: "90 days (Recommended)" }),
630
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "180", children: "180 days" }),
631
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "365", children: "1 year" }),
632
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "-1", children: "Forever" })
625
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "7", children: t("settings.general.retention.7days", "7 days") }),
626
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "30", children: t("settings.general.retention.30days", "30 days") }),
627
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "60", children: t("settings.general.retention.60days", "60 days") }),
628
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "90", children: t("settings.general.retention.90days", "90 days (Recommended)") }),
629
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "180", children: t("settings.general.retention.180days", "180 days") }),
630
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "365", children: t("settings.general.retention.1year", "1 year") }),
631
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "-1", children: t("settings.general.retention.forever", "Forever") })
633
632
  ]
634
633
  }
635
634
  ),
636
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: [
637
- "Old sessions deleted after ",
638
- settings.retentionDays === -1 ? "never" : `${settings.retentionDays} days`
639
- ] })
635
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "11px", marginTop: "8px" }, children: settings.retentionDays === -1 ? t("settings.general.retention.hintNever", "Old sessions deleted after never") : t("settings.general.retention.hint", "Old sessions deleted after {days}", { days: `${settings.retentionDays} days` }) })
640
636
  ] }) }),
641
637
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, background: "danger100", style: { borderRadius: theme.borderRadius.md, border: `2px solid ${theme.colors.danger[200]}` }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "flex-start", children: [
642
638
  /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, { style: { width: "18px", height: "18px", color: theme.colors.danger[600], flexShrink: 0, marginTop: "2px" } }),
643
639
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
644
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "danger700", style: { marginBottom: "8px", display: "block" }, children: "Danger Zone" }),
645
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "danger600", style: { fontSize: "13px", lineHeight: "1.7" }, children: [
646
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Clean All Inactive:" }),
647
- " Permanently deletes all inactive sessions. This cannot be undone."
648
- ] })
640
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "danger700", style: { marginBottom: "8px", display: "block" }, children: t("settings.general.danger.title", "Danger Zone") }),
641
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger600", style: { fontSize: "13px", lineHeight: "1.7" }, children: t("settings.general.danger.description", "Clean All Inactive: Permanently deletes all inactive sessions. This cannot be undone.") })
649
642
  ] }),
650
643
  /* @__PURE__ */ jsxRuntime.jsx(
651
644
  designSystem.Button,
@@ -656,7 +649,7 @@ const SettingsPage = () => {
656
649
  variant: "danger",
657
650
  size: "S",
658
651
  style: { flexShrink: 0 },
659
- children: "Clean Now"
652
+ children: t("settings.general.danger.cleanNow", "Clean Now")
660
653
  }
661
654
  )
662
655
  ] }) }) })
@@ -668,12 +661,12 @@ const SettingsPage = () => {
668
661
  designSystem.Accordion.Trigger,
669
662
  {
670
663
  icon: icons.Shield,
671
- description: "Security policies and threat protection",
672
- children: "Security Settings"
664
+ description: t("settings.security.description", "Security policies and threat protection"),
665
+ children: t("settings.security.title", "Security Settings")
673
666
  }
674
667
  ) }),
675
668
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, children: [
676
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: "SECURITY OPTIONS" }),
669
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: t("settings.security.options", "SECURITY OPTIONS") }),
677
670
  /* @__PURE__ */ jsxRuntime.jsx(
678
671
  designSystem.Box,
679
672
  {
@@ -688,32 +681,26 @@ const SettingsPage = () => {
688
681
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 4, children: [
689
682
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 3, children: [
690
683
  /* @__PURE__ */ jsxRuntime.jsx(icons.Shield, { style: { width: 24, height: 24, color: theme.colors.primary[600] } }),
691
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", children: "JWT Encryption Key Generator" })
684
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", children: t("settings.security.encryption.title", "JWT Encryption Key Generator") })
692
685
  ] }),
693
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", style: { lineHeight: 1.6 }, children: "Generate a secure 32-character encryption key for JWT token storage. This key is used to encrypt tokens before saving them to the database." }),
694
- /* @__PURE__ */ jsxRuntime.jsxs(
686
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", style: { lineHeight: 1.6 }, children: t("settings.security.encryption.description", "Generate a secure 32-character encryption key for JWT token storage. This key is used to encrypt tokens before saving them to the database.") }),
687
+ /* @__PURE__ */ jsxRuntime.jsx(
695
688
  designSystem.Alert,
696
689
  {
697
690
  variant: "default",
698
- title: "Important",
691
+ title: t("settings.security.encryption.important", "Important"),
699
692
  style: { marginTop: 8 },
700
- children: [
701
- "Add this key to your ",
702
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: ".env" }),
703
- " file as ",
704
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "SESSION_ENCRYPTION_KEY" }),
705
- " for production."
706
- ]
693
+ children: t("settings.security.encryption.envHint", "Add this key to your .env file as SESSION_ENCRYPTION_KEY for production.")
707
694
  }
708
695
  ),
709
696
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "flex-end", children: [
710
697
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { flex: 1 }, children: /* @__PURE__ */ jsxRuntime.jsx(
711
698
  designSystem.TextInput,
712
699
  {
713
- label: "Generated Encryption Key",
700
+ label: t("settings.security.encryption.label", "Generated Encryption Key"),
714
701
  value: encryptionKey,
715
702
  onChange: (e) => setEncryptionKey(e.target.value),
716
- placeholder: "Click 'Generate Key' to create a secure key",
703
+ placeholder: t("settings.security.encryption.placeholder", "Click 'Generate Key' to create a secure key"),
717
704
  type: showEncryptionKey ? "text" : "password"
718
705
  }
719
706
  ) }),
@@ -723,7 +710,7 @@ const SettingsPage = () => {
723
710
  variant: "secondary",
724
711
  onClick: () => setShowEncryptionKey(!showEncryptionKey),
725
712
  size: "L",
726
- children: showEncryptionKey ? "Hide" : "Show"
713
+ children: showEncryptionKey ? t("settings.security.encryption.hide", "Hide") : t("settings.security.encryption.show", "Show")
727
714
  }
728
715
  )
729
716
  ] }),
@@ -739,11 +726,11 @@ const SettingsPage = () => {
739
726
  setShowEncryptionKey(true);
740
727
  toggleNotification({
741
728
  type: "success",
742
- message: "32-character encryption key generated!"
729
+ message: t("notifications.success.keyGenerated", "32-character encryption key generated!")
743
730
  });
744
731
  },
745
732
  size: "L",
746
- children: "Generate Key"
733
+ children: t("settings.security.encryption.generate", "Generate Key")
747
734
  }
748
735
  ),
749
736
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -756,13 +743,13 @@ const SettingsPage = () => {
756
743
  navigator.clipboard.writeText(encryptionKey);
757
744
  toggleNotification({
758
745
  type: "success",
759
- message: "Encryption key copied to clipboard!"
746
+ message: t("notifications.success.keyCopied", "Encryption key copied to clipboard!")
760
747
  });
761
748
  }
762
749
  },
763
750
  disabled: !encryptionKey,
764
751
  size: "L",
765
- children: "Copy to Clipboard"
752
+ children: t("settings.security.encryption.copy", "Copy to Clipboard")
766
753
  }
767
754
  ),
768
755
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -776,13 +763,13 @@ const SettingsPage = () => {
776
763
  navigator.clipboard.writeText(envLine);
777
764
  toggleNotification({
778
765
  type: "success",
779
- message: "Copied as .env format!"
766
+ message: t("notifications.success.envCopied", "Copied as .env format!")
780
767
  });
781
768
  }
782
769
  },
783
770
  disabled: !encryptionKey,
784
771
  size: "L",
785
- children: "Copy for .env"
772
+ children: t("settings.security.encryption.copyEnv", "Copy for .env")
786
773
  }
787
774
  )
788
775
  ] }),
@@ -799,7 +786,7 @@ const SettingsPage = () => {
799
786
  wordBreak: "break-all"
800
787
  },
801
788
  children: [
802
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", style: { marginBottom: 8, display: "block" }, children: "Add to .env file:" }),
789
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", style: { marginBottom: 8, display: "block" }, children: t("settings.security.encryption.envLabel", "Add to .env file:") }),
803
790
  /* @__PURE__ */ jsxRuntime.jsxs("code", { style: { color: theme.colors.primary[700] }, children: [
804
791
  "SESSION_ENCRYPTION_KEY=",
805
792
  encryptionKey
@@ -832,10 +819,10 @@ const SettingsPage = () => {
832
819
  fontWeight: "bold",
833
820
  textColor: settings.blockSuspiciousSessions ? "success700" : "neutral800",
834
821
  style: { fontSize: "16px" },
835
- children: "Block Suspicious Sessions"
822
+ children: t("settings.security.blockSuspicious.title", "Block Suspicious Sessions")
836
823
  }
837
824
  ),
838
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: "Automatically block sessions from VPNs, proxies, or threat IPs" })
825
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: t("settings.security.blockSuspicious.description", "Automatically block sessions from VPNs, proxies, or threat IPs") })
839
826
  ] })
840
827
  ] })
841
828
  }
@@ -862,10 +849,10 @@ const SettingsPage = () => {
862
849
  fontWeight: "bold",
863
850
  textColor: settings.enableGeolocation ? "success700" : "neutral800",
864
851
  style: { fontSize: "16px" },
865
- children: "IP Geolocation"
852
+ children: t("settings.security.geolocation.title", "IP Geolocation")
866
853
  }
867
854
  ),
868
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: "Fetch location data for each session (Premium)" })
855
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: t("settings.security.geolocation.description", "Fetch location data for each session (Premium)") })
869
856
  ] })
870
857
  ] })
871
858
  }
@@ -891,10 +878,10 @@ const SettingsPage = () => {
891
878
  fontWeight: "bold",
892
879
  textColor: settings.enableSecurityScoring ? "success700" : "neutral800",
893
880
  style: { fontSize: "16px" },
894
- children: "Security Scoring"
881
+ children: t("settings.security.scoring.title", "Security Scoring")
895
882
  }
896
883
  ),
897
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: "Calculate security scores and detect threats (Premium)" })
884
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: t("settings.security.scoring.description", "Calculate security scores and detect threats (Premium)") })
898
885
  ] })
899
886
  ] })
900
887
  }
@@ -902,7 +889,10 @@ const SettingsPage = () => {
902
889
  ] })
903
890
  ] }) }),
904
891
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 6, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
905
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: "🚫 Max Failed Login Attempts" }),
892
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: [
893
+ "🚫 ",
894
+ t("settings.security.maxFailed.title", "Max Failed Login Attempts")
895
+ ] }),
906
896
  /* @__PURE__ */ jsxRuntime.jsx(
907
897
  designSystem.NumberInput,
908
898
  {
@@ -912,11 +902,7 @@ const SettingsPage = () => {
912
902
  max: 20
913
903
  }
914
904
  ),
915
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 2, background: "warning50", style: { borderRadius: "4px", marginTop: "8px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "warning700", style: { fontSize: "11px" }, children: [
916
- "User will be blocked after ",
917
- settings.maxFailedLogins,
918
- " failed attempts"
919
- ] }) })
905
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 2, background: "warning50", style: { borderRadius: "4px", marginTop: "8px" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "warning700", style: { fontSize: "11px" }, children: t("settings.security.maxFailed.hint", "User will be blocked after {count} failed attempts", { count: settings.maxFailedLogins }) }) })
920
906
  ] }) }) })
921
907
  ] }) })
922
908
  ] }),
@@ -925,14 +911,17 @@ const SettingsPage = () => {
925
911
  designSystem.Accordion.Trigger,
926
912
  {
927
913
  icon: icons.Mail,
928
- description: "Email alerts for security events",
929
- children: "Email Notifications (Advanced)"
914
+ description: t("settings.email.description", "Email alerts for security events"),
915
+ children: t("settings.email.title", "Email Notifications (Advanced)")
930
916
  }
931
917
  ) }),
932
918
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, children: [
933
919
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { background: "neutral100", padding: 5, style: { borderRadius: theme.borderRadius.md, marginBottom: "32px" }, children: [
934
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "8px", display: "block", textAlign: "center", color: theme.colors.neutral[700] }, children: "📧 EMAIL ALERTS" }),
935
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "20px", display: "block", textAlign: "center", fontSize: "12px" }, children: "Send security alerts to users via email" }),
920
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "8px", display: "block", textAlign: "center", color: theme.colors.neutral[700] }, children: [
921
+ "📧 ",
922
+ t("settings.email.alerts.title", "EMAIL ALERTS")
923
+ ] }),
924
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "20px", display: "block", textAlign: "center", fontSize: "12px" }, children: t("settings.email.alerts.subtitle", "Send security alerts to users via email") }),
936
925
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
937
926
  ToggleCard,
938
927
  {
@@ -954,17 +943,20 @@ const SettingsPage = () => {
954
943
  fontWeight: "bold",
955
944
  textColor: settings.enableEmailAlerts ? "success700" : "neutral800",
956
945
  style: { fontSize: "16px" },
957
- children: "Enable Email Alerts"
946
+ children: t("settings.email.enable.title", "Enable Email Alerts")
958
947
  }
959
948
  ),
960
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: "Send security alerts for suspicious logins, new locations, and VPN/Proxy usage" })
949
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: t("settings.email.enable.description", "Send security alerts for suspicious logins, new locations, and VPN/Proxy usage") })
961
950
  ] })
962
951
  ] })
963
952
  }
964
953
  ) }) })
965
954
  ] }),
966
955
  settings.enableEmailAlerts && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
967
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: "⚙️ ALERT TYPES" }),
956
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "16px", display: "block", color: theme.colors.neutral[700] }, children: [
957
+ "⚙️ ",
958
+ t("settings.email.types.title", "ALERT TYPES")
959
+ ] }),
968
960
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 4, style: { marginBottom: "32px" }, children: [
969
961
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
970
962
  designSystem.Box,
@@ -983,7 +975,7 @@ const SettingsPage = () => {
983
975
  {
984
976
  checked: settings.alertOnSuspiciousLogin,
985
977
  onChange: () => handleChange("alertOnSuspiciousLogin", !settings.alertOnSuspiciousLogin),
986
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", style: { fontSize: "14px" }, children: "Suspicious Login" })
978
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", style: { fontSize: "14px" }, children: t("settings.email.types.suspicious", "Suspicious Login") })
987
979
  }
988
980
  )
989
981
  }
@@ -1005,7 +997,7 @@ const SettingsPage = () => {
1005
997
  {
1006
998
  checked: settings.alertOnNewLocation,
1007
999
  onChange: () => handleChange("alertOnNewLocation", !settings.alertOnNewLocation),
1008
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", style: { fontSize: "14px" }, children: "New Location" })
1000
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", style: { fontSize: "14px" }, children: t("settings.email.types.newLocation", "New Location") })
1009
1001
  }
1010
1002
  )
1011
1003
  }
@@ -1027,24 +1019,24 @@ const SettingsPage = () => {
1027
1019
  {
1028
1020
  checked: settings.alertOnVpnProxy,
1029
1021
  onChange: () => handleChange("alertOnVpnProxy", !settings.alertOnVpnProxy),
1030
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", style: { fontSize: "14px" }, children: "VPN/Proxy" })
1022
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "semiBold", style: { fontSize: "14px" }, children: t("settings.email.types.vpnProxy", "VPN/Proxy") })
1031
1023
  }
1032
1024
  )
1033
1025
  }
1034
1026
  ) })
1035
1027
  ] }),
1036
1028
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, { style: { marginBottom: "24px" } }),
1037
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "8px", display: "block", color: theme.colors.neutral[700] }, children: "EMAIL TEMPLATES" }),
1038
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "20px", display: "block", fontSize: "12px" }, children: "Customize email notification templates with dynamic variables" }),
1029
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", fontWeight: "bold", style: { marginBottom: "8px", display: "block", color: theme.colors.neutral[700] }, children: t("settings.email.templates.title", "EMAIL TEMPLATES") }),
1030
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "20px", display: "block", fontSize: "12px" }, children: t("settings.email.templates.subtitle", "Customize email notification templates with dynamic variables") }),
1039
1031
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Root, { value: activeTemplateTab, onValueChange: setActiveTemplateTab, children: [
1040
1032
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.List, { "aria-label": "Email Templates", children: [
1041
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "suspiciousLogin", children: "Suspicious Login" }),
1042
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "newLocation", children: "New Location" }),
1043
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "vpnProxy", children: "VPN/Proxy" })
1033
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "suspiciousLogin", children: t("settings.email.templates.tab.suspicious", "Suspicious Login") }),
1034
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "newLocation", children: t("settings.email.templates.tab.newLocation", "New Location") }),
1035
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "vpnProxy", children: t("settings.email.templates.tab.vpnProxy", "VPN/Proxy") })
1044
1036
  ] }),
1045
1037
  Object.keys(settings.emailTemplates).map((templateKey) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: templateKey, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { paddingTop: 4, children: [
1046
1038
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { marginBottom: "24px" }, children: [
1047
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: "Email Subject" }),
1039
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "8px", display: "block" }, children: t("settings.email.templates.subject", "Email Subject") }),
1048
1040
  /* @__PURE__ */ jsxRuntime.jsx(
1049
1041
  designSystem.TextInput,
1050
1042
  {
@@ -1054,7 +1046,7 @@ const SettingsPage = () => {
1054
1046
  newTemplates[templateKey].subject = e.target.value;
1055
1047
  handleChange("emailTemplates", newTemplates);
1056
1048
  },
1057
- placeholder: "Enter email subject..."
1049
+ placeholder: t("settings.email.templates.subjectPlaceholder", "Enter email subject...")
1058
1050
  }
1059
1051
  )
1060
1052
  ] }),
@@ -1067,7 +1059,7 @@ const SettingsPage = () => {
1067
1059
  children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
1068
1060
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 2, children: [
1069
1061
  /* @__PURE__ */ jsxRuntime.jsx(icons.Code, { style: { width: "16px", height: "16px", color: theme.colors.primary[600] } }),
1070
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "primary600", children: "Available Variables (click to copy)" })
1062
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: "primary600", children: t("settings.email.templates.variables", "Available Variables (click to copy)") })
1071
1063
  ] }),
1072
1064
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, wrap: "wrap", children: TEMPLATE_VARIABLES[templateKey].map(({ var: variable, desc }) => /* @__PURE__ */ jsxRuntime.jsx(
1073
1065
  designSystem.Button,
@@ -1076,7 +1068,7 @@ const SettingsPage = () => {
1076
1068
  variant: "tertiary",
1077
1069
  onClick: () => {
1078
1070
  navigator.clipboard.writeText(variable);
1079
- toggleNotification({ type: "success", message: `${variable} copied!` });
1071
+ toggleNotification({ type: "success", message: t("notifications.success.variableCopied", "{variable} copied!", { variable }) });
1080
1072
  },
1081
1073
  style: {
1082
1074
  fontFamily: "monospace",
@@ -1100,10 +1092,13 @@ const SettingsPage = () => {
1100
1092
  children: [
1101
1093
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", style: { marginBottom: "16px" }, children: [
1102
1094
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 2, children: [
1103
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", style: { fontSize: "18px" }, children: "🎨 HTML Template" }),
1104
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { variant: "success", children: "Main Template" })
1095
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "delta", fontWeight: "bold", style: { fontSize: "18px" }, children: [
1096
+ "🎨 ",
1097
+ t("settings.email.templates.html.title", "HTML Template")
1098
+ ] }),
1099
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { variant: "success", children: t("settings.email.templates.html.badge", "Main Template") })
1105
1100
  ] }),
1106
- /* @__PURE__ */ jsxRuntime.jsx(
1101
+ /* @__PURE__ */ jsxRuntime.jsxs(
1107
1102
  designSystem.Button,
1108
1103
  {
1109
1104
  variant: "tertiary",
@@ -1113,17 +1108,16 @@ const SettingsPage = () => {
1113
1108
  const newTemplates = { ...settings.emailTemplates };
1114
1109
  newTemplates[templateKey].html = defaultTemplates[templateKey].html;
1115
1110
  handleChange("emailTemplates", newTemplates);
1116
- toggleNotification({ type: "success", message: "Default HTML template loaded!" });
1111
+ toggleNotification({ type: "success", message: t("notifications.success.defaultLoaded", "Default template loaded!") });
1117
1112
  },
1118
- children: "📋 Load Default"
1113
+ children: [
1114
+ "📋 ",
1115
+ t("settings.email.templates.html.loadDefault", "Load Default")
1116
+ ]
1119
1117
  }
1120
1118
  )
1121
1119
  ] }),
1122
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "16px", display: "block", fontSize: "14px" }, children: [
1123
- "HTML template for email notifications. Use variables like ",
1124
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: "{{user.email}}" }),
1125
- " for dynamic content."
1126
- ] }),
1120
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "16px", display: "block", fontSize: "14px" }, children: t("settings.email.templates.html.description", "HTML template for email notifications. Use variables like {{user.email}} for dynamic content.") }),
1127
1121
  /* @__PURE__ */ jsxRuntime.jsxs(
1128
1122
  designSystem.Box,
1129
1123
  {
@@ -1179,19 +1173,22 @@ const SettingsPage = () => {
1179
1173
  }
1180
1174
  ),
1181
1175
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, style: { marginTop: "12px" }, wrap: "wrap", children: [
1182
- /* @__PURE__ */ jsxRuntime.jsx(
1176
+ /* @__PURE__ */ jsxRuntime.jsxs(
1183
1177
  designSystem.Button,
1184
1178
  {
1185
1179
  variant: "secondary",
1186
1180
  size: "S",
1187
1181
  onClick: () => {
1188
1182
  navigator.clipboard.writeText(settings.emailTemplates[templateKey].html);
1189
- toggleNotification({ type: "success", message: "HTML template copied!" });
1183
+ toggleNotification({ type: "success", message: t("notifications.success.htmlCopied", "HTML template copied!") });
1190
1184
  },
1191
- children: "📋 Copy Template"
1185
+ children: [
1186
+ "📋 ",
1187
+ t("settings.email.templates.html.copy", "Copy Template")
1188
+ ]
1192
1189
  }
1193
1190
  ),
1194
- /* @__PURE__ */ jsxRuntime.jsx(
1191
+ /* @__PURE__ */ jsxRuntime.jsxs(
1195
1192
  designSystem.Button,
1196
1193
  {
1197
1194
  variant: "tertiary",
@@ -1200,13 +1197,16 @@ const SettingsPage = () => {
1200
1197
  const validation = validateTemplate(settings.emailTemplates[templateKey].html, templateKey);
1201
1198
  toggleNotification({
1202
1199
  type: validation.isValid ? "success" : "warning",
1203
- message: validation.isValid ? `✓ Template valid! Found ${validation.foundVars.length}/${validation.totalAvailable} variables.` : "[WARNING] No variables found. Add at least one variable."
1200
+ message: validation.isValid ? t("notifications.success.validated", "Template valid! Found {found}/{total} variables.", { found: validation.foundVars.length, total: validation.totalAvailable }) : t("notifications.warning.noVariables", "[WARNING] No variables found. Add at least one variable.")
1204
1201
  });
1205
1202
  },
1206
- children: "✓ Validate"
1203
+ children: [
1204
+ "✓ ",
1205
+ t("settings.email.templates.html.validate", "Validate")
1206
+ ]
1207
1207
  }
1208
1208
  ),
1209
- /* @__PURE__ */ jsxRuntime.jsx(
1209
+ /* @__PURE__ */ jsxRuntime.jsxs(
1210
1210
  designSystem.Button,
1211
1211
  {
1212
1212
  variant: "tertiary",
@@ -1216,10 +1216,13 @@ const SettingsPage = () => {
1216
1216
  const chars = settings.emailTemplates[templateKey].html.length;
1217
1217
  toggleNotification({
1218
1218
  type: "info",
1219
- message: `Template has ${lines} lines and ${chars} characters`
1219
+ message: t("notifications.info.templateStats", "Template has {lines} lines and {chars} characters", { lines, chars })
1220
1220
  });
1221
1221
  },
1222
- children: "ℹ️ Template Info"
1222
+ children: [
1223
+ "ℹ️ ",
1224
+ t("settings.email.templates.html.info", "Template Info")
1225
+ ]
1223
1226
  }
1224
1227
  )
1225
1228
  ] })
@@ -1235,10 +1238,13 @@ const SettingsPage = () => {
1235
1238
  children: [
1236
1239
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", style: { marginBottom: "16px" }, children: [
1237
1240
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", gap: 2, children: [
1238
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", fontWeight: "bold", style: { fontSize: "18px" }, children: "📄 Text Template" }),
1239
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { variant: "secondary", children: "Fallback" })
1241
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "delta", fontWeight: "bold", style: { fontSize: "18px" }, children: [
1242
+ "📄 ",
1243
+ t("settings.email.templates.text.title", "Text Template")
1244
+ ] }),
1245
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { variant: "secondary", children: t("settings.email.templates.text.badge", "Fallback") })
1240
1246
  ] }),
1241
- /* @__PURE__ */ jsxRuntime.jsx(
1247
+ /* @__PURE__ */ jsxRuntime.jsxs(
1242
1248
  designSystem.Button,
1243
1249
  {
1244
1250
  variant: "tertiary",
@@ -1248,13 +1254,16 @@ const SettingsPage = () => {
1248
1254
  const newTemplates = { ...settings.emailTemplates };
1249
1255
  newTemplates[templateKey].text = defaultTemplates[templateKey].text;
1250
1256
  handleChange("emailTemplates", newTemplates);
1251
- toggleNotification({ type: "success", message: "Default text template loaded!" });
1257
+ toggleNotification({ type: "success", message: t("notifications.success.defaultLoaded", "Default template loaded!") });
1252
1258
  },
1253
- children: "📋 Load Default"
1259
+ children: [
1260
+ "📋 ",
1261
+ t("settings.email.templates.text.loadDefault", "Load Default")
1262
+ ]
1254
1263
  }
1255
1264
  )
1256
1265
  ] }),
1257
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "16px", display: "block", fontSize: "14px" }, children: "Plain text version (no HTML) as fallback for older email clients" }),
1266
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "16px", display: "block", fontSize: "14px" }, children: t("settings.email.templates.text.description", "Plain text version (no HTML) as fallback for older email clients") }),
1258
1267
  /* @__PURE__ */ jsxRuntime.jsxs(
1259
1268
  designSystem.Box,
1260
1269
  {
@@ -1309,16 +1318,19 @@ const SettingsPage = () => {
1309
1318
  ]
1310
1319
  }
1311
1320
  ),
1312
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, style: { marginTop: "12px" }, wrap: "wrap", children: /* @__PURE__ */ jsxRuntime.jsx(
1321
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, style: { marginTop: "12px" }, wrap: "wrap", children: /* @__PURE__ */ jsxRuntime.jsxs(
1313
1322
  designSystem.Button,
1314
1323
  {
1315
1324
  variant: "secondary",
1316
1325
  size: "S",
1317
1326
  onClick: () => {
1318
1327
  navigator.clipboard.writeText(settings.emailTemplates[templateKey].text);
1319
- toggleNotification({ type: "success", message: "Text template copied!" });
1328
+ toggleNotification({ type: "success", message: t("notifications.success.textCopied", "Text template copied!") });
1320
1329
  },
1321
- children: "📋 Copy Template"
1330
+ children: [
1331
+ "📋 ",
1332
+ t("settings.email.templates.text.copy", "Copy Template")
1333
+ ]
1322
1334
  }
1323
1335
  ) })
1324
1336
  ]
@@ -1334,8 +1346,8 @@ const SettingsPage = () => {
1334
1346
  designSystem.Accordion.Trigger,
1335
1347
  {
1336
1348
  icon: icons.Code,
1337
- description: "Discord & Slack integration",
1338
- children: "Webhook Integration (Advanced)"
1349
+ description: t("settings.webhooks.description", "Discord & Slack integration"),
1350
+ children: t("settings.webhooks.title", "Webhook Integration (Advanced)")
1339
1351
  }
1340
1352
  ) }),
1341
1353
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, children: [
@@ -1360,17 +1372,20 @@ const SettingsPage = () => {
1360
1372
  fontWeight: "bold",
1361
1373
  textColor: settings.enableWebhooks ? "success700" : "neutral800",
1362
1374
  style: { fontSize: "16px" },
1363
- children: "Enable Webhooks"
1375
+ children: t("settings.webhooks.enable.title", "Enable Webhooks")
1364
1376
  }
1365
1377
  ),
1366
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: "Send session events to Discord, Slack, or custom endpoints" })
1378
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "13px", lineHeight: "1.6" }, children: t("settings.webhooks.enable.description", "Send session events to Discord, Slack, or custom endpoints") })
1367
1379
  ] })
1368
1380
  ] })
1369
1381
  }
1370
1382
  ) }) }) }),
1371
1383
  settings.enableWebhooks && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 6, children: [
1372
1384
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
1373
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "12px", display: "block" }, children: "🔗 Discord Webhook URL" }),
1385
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "12px", display: "block" }, children: [
1386
+ "🔗 ",
1387
+ t("settings.webhooks.discord.title", "Discord Webhook URL")
1388
+ ] }),
1374
1389
  /* @__PURE__ */ jsxRuntime.jsx(
1375
1390
  designSystem.Box,
1376
1391
  {
@@ -1383,7 +1398,7 @@ const SettingsPage = () => {
1383
1398
  children: /* @__PURE__ */ jsxRuntime.jsx(
1384
1399
  "textarea",
1385
1400
  {
1386
- placeholder: "https://discord.com/api/webhooks/123456789/abcdefghijklmnopqrstuvwxyz...",
1401
+ placeholder: t("settings.webhooks.discord.placeholder", "https://discord.com/api/webhooks/123456789/abcdefghijklmnopqrstuvwxyz..."),
1387
1402
  value: settings.discordWebhookUrl,
1388
1403
  onChange: (e) => handleChange("discordWebhookUrl", e.target.value),
1389
1404
  rows: 3,
@@ -1405,15 +1420,15 @@ const SettingsPage = () => {
1405
1420
  }
1406
1421
  ),
1407
1422
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", style: { marginTop: "10px" }, children: [
1408
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: "Optional: Post session alerts to your Discord channel" }),
1409
- settings.discordWebhookUrl && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "primary600", style: { fontSize: "11px", fontFamily: "monospace" }, children: [
1410
- settings.discordWebhookUrl.length,
1411
- " characters"
1412
- ] })
1423
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: t("settings.webhooks.discord.hint", "Optional: Post session alerts to your Discord channel") }),
1424
+ settings.discordWebhookUrl && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "primary600", style: { fontSize: "11px", fontFamily: "monospace" }, children: t("settings.webhooks.characters", "{count} characters", { count: settings.discordWebhookUrl.length }) })
1413
1425
  ] })
1414
1426
  ] }) }),
1415
1427
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
1416
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "12px", display: "block" }, children: "💬 Slack Webhook URL" }),
1428
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", fontWeight: "bold", style: { marginBottom: "12px", display: "block" }, children: [
1429
+ "💬 ",
1430
+ t("settings.webhooks.slack.title", "Slack Webhook URL")
1431
+ ] }),
1417
1432
  /* @__PURE__ */ jsxRuntime.jsx(
1418
1433
  designSystem.Box,
1419
1434
  {
@@ -1426,7 +1441,7 @@ const SettingsPage = () => {
1426
1441
  children: /* @__PURE__ */ jsxRuntime.jsx(
1427
1442
  "textarea",
1428
1443
  {
1429
- placeholder: "https://hooks.slack.com/services/XXXX/XXXX/XXXX",
1444
+ placeholder: t("settings.webhooks.slack.placeholder", "https://hooks.slack.com/services/XXXX/XXXX/XXXX"),
1430
1445
  value: settings.slackWebhookUrl,
1431
1446
  onChange: (e) => handleChange("slackWebhookUrl", e.target.value),
1432
1447
  rows: 3,
@@ -1448,11 +1463,8 @@ const SettingsPage = () => {
1448
1463
  }
1449
1464
  ),
1450
1465
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", style: { marginTop: "10px" }, children: [
1451
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: "Optional: Post session alerts to your Slack workspace" }),
1452
- settings.slackWebhookUrl && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", textColor: "primary600", style: { fontSize: "11px", fontFamily: "monospace" }, children: [
1453
- settings.slackWebhookUrl.length,
1454
- " characters"
1455
- ] })
1466
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", style: { fontSize: "12px" }, children: t("settings.webhooks.slack.hint", "Optional: Post session alerts to your Slack workspace") }),
1467
+ settings.slackWebhookUrl && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "primary600", style: { fontSize: "11px", fontFamily: "monospace" }, children: t("settings.webhooks.characters", "{count} characters", { count: settings.slackWebhookUrl.length }) })
1456
1468
  ] })
1457
1469
  ] }) })
1458
1470
  ] })
@@ -1462,8 +1474,8 @@ const SettingsPage = () => {
1462
1474
  /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 5, background: "primary100", style: { borderRadius: theme.borderRadius.md, marginTop: "32px", border: "2px solid #BAE6FD" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 3, alignItems: "flex-start", children: [
1463
1475
  /* @__PURE__ */ jsxRuntime.jsx(icons.Check, { style: { width: "20px", height: "20px", color: theme.colors.success[600], flexShrink: 0, marginTop: "2px" } }),
1464
1476
  /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { style: { flex: 1 }, children: [
1465
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", style: { marginBottom: "8px", display: "block", color: theme.colors.primary[700] }, children: "Database-Backed Settings" }),
1466
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "primary700", style: { fontSize: "13px", lineHeight: "1.8" }, children: "All settings are stored in your Strapi database and shared across all admin users. Changes take effect immediately - no server restart required! Email templates, webhooks, and security options are all managed from this interface." })
1477
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", style: { marginBottom: "8px", display: "block", color: theme.colors.primary[700] }, children: t("settings.footer.title", "Database-Backed Settings") }),
1478
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "primary700", style: { fontSize: "13px", lineHeight: "1.8" }, children: t("settings.footer.description", "All settings are stored in your Strapi database and shared across all admin users. Changes take effect immediately - no server restart required! Email templates, webhooks, and security options are all managed from this interface.") })
1467
1479
  ] })
1468
1480
  ] }) })
1469
1481
  ] })