@saasicat/ui-vue 0.5.0 → 0.7.0

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 (186) hide show
  1. package/README.md +17 -0
  2. package/dist/{chunk-EH7TOD4H.js → chunk-A3W2N26K.js} +73 -77
  3. package/dist/{chunk-3YP2ZAOD.js → chunk-QZOSDCNP.js} +36 -1
  4. package/dist/chunk-X5SQ5HMB.js +3231 -0
  5. package/dist/client/index.cjs +3279 -76
  6. package/dist/client/index.d.cts +31 -5
  7. package/dist/client/index.d.ts +31 -5
  8. package/dist/client/index.js +23 -5
  9. package/dist/index.cjs +3709 -465
  10. package/dist/index.d.cts +37 -54
  11. package/dist/index.d.ts +37 -54
  12. package/dist/index.js +347 -311
  13. package/dist/messages-7b0P8W75.d.cts +1652 -0
  14. package/dist/messages-7b0P8W75.d.ts +1652 -0
  15. package/dist/quasar/index.cjs +3185 -4
  16. package/dist/quasar/index.d.cts +11 -2
  17. package/dist/quasar/index.d.ts +11 -2
  18. package/dist/quasar/index.js +8 -3
  19. package/dist/testing-e2e/admin-pages-suite.cjs +14 -11
  20. package/dist/testing-e2e/admin-pages-suite.js +14 -11
  21. package/dist/{ui-notify-COUzXEQ4.d.ts → use-super-admin-i18n-B3v3-SWZ.d.ts} +35 -3
  22. package/dist/{ui-notify-D_eAAwRh.d.cts → use-super-admin-i18n-DMktRVEt.d.cts} +35 -3
  23. package/package.json +2 -2
  24. package/src/client/action-registry.ts +4 -4
  25. package/src/client/batch-column-fetcher.ts +4 -4
  26. package/src/client/boot-loader.ts +3 -3
  27. package/src/client/i18n/currency.ts +42 -0
  28. package/src/client/i18n/define.ts +59 -0
  29. package/src/client/i18n/format.ts +12 -0
  30. package/src/client/i18n/index.ts +14 -0
  31. package/src/client/i18n/locale.ts +15 -0
  32. package/src/client/i18n/messages/audit.ts +42 -0
  33. package/src/client/i18n/messages/bundles.ts +459 -0
  34. package/src/client/i18n/messages/common.ts +147 -0
  35. package/src/client/i18n/messages/dashboard.ts +16 -0
  36. package/src/client/i18n/messages/discovery.ts +229 -0
  37. package/src/client/i18n/messages/email.ts +125 -0
  38. package/src/client/i18n/messages/marketing.ts +270 -0
  39. package/src/client/i18n/messages/nav.ts +72 -0
  40. package/src/client/i18n/messages/pilots.ts +192 -0
  41. package/src/client/i18n/messages/plan-detail.ts +266 -0
  42. package/src/client/i18n/messages/plan-editor.ts +177 -0
  43. package/src/client/i18n/messages/plan-versions.ts +251 -0
  44. package/src/client/i18n/messages/plans.ts +503 -0
  45. package/src/client/i18n/messages/promos.ts +202 -0
  46. package/src/client/i18n/messages/shell.ts +145 -0
  47. package/src/client/i18n/messages/tenants.ts +104 -0
  48. package/src/client/i18n/messages/users.ts +78 -0
  49. package/src/client/i18n/messages.ts +84 -0
  50. package/src/client/index.ts +2 -0
  51. package/src/client/manifest-loader.ts +4 -4
  52. package/src/client/nav-builder.ts +44 -51
  53. package/src/client/plan-versions-catalog.ts +42 -30
  54. package/src/components/BundleVersionPublishDialog.vue +35 -24
  55. package/src/components/MarketingPromotionsTab.vue +112 -59
  56. package/src/components/MfaPromptDialog.vue +11 -11
  57. package/src/components/TenantActionConfirmDialog.vue +19 -17
  58. package/src/components/VersionDiffPreview.vue +72 -43
  59. package/src/components/bundle-editor/BundleCreatePanel.vue +76 -63
  60. package/src/components/bundle-editor/BundleFeaturesEditor.vue +13 -6
  61. package/src/components/bundle-editor/BundlePlanCompatPicker.vue +19 -14
  62. package/src/components/bundle-editor/BundleQuotasEditor.vue +7 -4
  63. package/src/components/bundle-editor/BundleStatusBanner.vue +36 -19
  64. package/src/components/bundle-editor/BundleVersionInlineEditor.vue +51 -35
  65. package/src/components/bundle-editor/BundleVersionStrip.vue +24 -12
  66. package/src/components/bundle-editor/bundle-version-status.ts +29 -29
  67. package/src/components/dialogs/PilotCreateDialog.vue +58 -63
  68. package/src/components/dialogs/PilotEditDialog.vue +40 -34
  69. package/src/components/dialogs/PromoCodeCreateDialog.vue +89 -63
  70. package/src/components/dialogs/PromoCodeEditDialog.vue +98 -66
  71. package/src/components/dialogs/types.ts +3 -13
  72. package/src/components/plan/PlanCycleToggle.vue +20 -9
  73. package/src/components/plan-cockpit/PlanCockpit.vue +34 -15
  74. package/src/components/plan-cockpit/PlanCockpitAuditLog.vue +13 -6
  75. package/src/components/plan-cockpit/PlanCockpitDiffPanel.vue +18 -9
  76. package/src/components/plan-cockpit/PlanCockpitHeader.vue +9 -6
  77. package/src/components/plan-cockpit/PlanCockpitImpactPanel.vue +24 -11
  78. package/src/components/plan-cockpit/PlanCockpitKpis.vue +28 -17
  79. package/src/components/plan-cockpit/PlanCockpitVersions.vue +50 -25
  80. package/src/components/plan-create-dialog/PlanCreateDialog.vue +45 -35
  81. package/src/components/plan-detail/PlanAuditLog.vue +11 -6
  82. package/src/components/plan-detail/PlanDetail.vue +21 -23
  83. package/src/components/plan-detail/PlanDetailHeader.vue +20 -11
  84. package/src/components/plan-detail/PlanDetailKpis.vue +30 -17
  85. package/src/components/plan-detail/PlanTerminateDialog.vue +22 -9
  86. package/src/components/plan-detail/PlanVersionDiffPanel.vue +61 -27
  87. package/src/components/plan-detail/PlanVersionsPanel.vue +71 -36
  88. package/src/components/plan-list/PlanList.vue +99 -57
  89. package/src/components/plan-matrix/PlanMatrix.vue +85 -38
  90. package/src/components/plan-review/PlanReview.vue +105 -80
  91. package/src/components/plan-version-editor/PlanCatalogPreview.vue +43 -20
  92. package/src/components/plan-version-editor/PlanComponentPool.vue +15 -7
  93. package/src/components/plan-version-editor/PlanVersionBasket.vue +45 -24
  94. package/src/components/plan-version-editor/PlanVersionDiffDialog.vue +8 -7
  95. package/src/components/plan-version-editor/PlanVersionEditor.vue +74 -40
  96. package/src/components/plan-version-editor/PlanVersionEditorHeader.vue +24 -12
  97. package/src/index.ts +1 -1
  98. package/src/pages-standard/AdminLayout.vue +42 -17
  99. package/src/pages-standard/AdminManifestErrorPage.vue +10 -10
  100. package/src/pages-standard/AuditPage.vue +58 -19
  101. package/src/pages-standard/BundlesPage.vue +29 -18
  102. package/src/pages-standard/DashboardPage.vue +29 -15
  103. package/src/pages-standard/DiscoveryPage.vue +40 -28
  104. package/src/pages-standard/EmailHistoryPage.vue +92 -59
  105. package/src/pages-standard/MarketingCatalogPage.vue +35 -16
  106. package/src/pages-standard/PilotsPage.vue +57 -41
  107. package/src/pages-standard/PlanVersionsPage.vue +7 -3
  108. package/src/pages-standard/PlansPage.vue +89 -57
  109. package/src/pages-standard/PlatformEmailPage.vue +115 -50
  110. package/src/pages-standard/PromoCodeDetailPage.vue +66 -63
  111. package/src/pages-standard/PromoCodesPage.vue +46 -35
  112. package/src/pages-standard/SubscriptionsPage.vue +14 -9
  113. package/src/pages-standard/SuperAdminLoginPage.vue +16 -13
  114. package/src/pages-standard/SuperAdminSetupWizard.vue +51 -47
  115. package/src/pages-standard/TenantDetailPage.vue +50 -36
  116. package/src/pages-standard/TenantsPage.vue +54 -41
  117. package/src/pages-standard/UsersPage.vue +66 -42
  118. package/src/pages-standard/bundles-page/BundleAccordionList.vue +20 -8
  119. package/src/pages-standard/bundles-page/BundleDetailPanel.vue +28 -18
  120. package/src/pages-standard/bundles-page/BundlesFilterBar.vue +4 -1
  121. package/src/pages-standard/bundles-page/BundlesHeader.vue +9 -8
  122. package/src/pages-standard/bundles-page/BundlesKpis.vue +29 -11
  123. package/src/pages-standard/discovery-page/CatalogEntryTransPanel.vue +20 -8
  124. package/src/pages-standard/discovery-page/DiscoveryCapList.vue +5 -3
  125. package/src/pages-standard/discovery-page/DiscoveryFeatureCard.vue +43 -24
  126. package/src/pages-standard/discovery-page/DiscoveryHeader.vue +7 -4
  127. package/src/pages-standard/discovery-page/DiscoveryKpis.vue +28 -15
  128. package/src/pages-standard/discovery-page/DiscoveryQuotaCard.vue +20 -10
  129. package/src/pages-standard/discovery-page/DiscoveryStatusControl.vue +9 -6
  130. package/src/pages-standard/discovery-page/discovery-ui.ts +40 -52
  131. package/src/pages-standard/marketing-catalog/MarketingCatalogAdmin.vue +81 -49
  132. package/src/pages-standard/marketing-catalog/MarketingCatalogHeader.vue +13 -10
  133. package/src/pages-standard/marketing-catalog/MarketingCatalogPreview.vue +24 -20
  134. package/src/pages-standard/marketing-catalog/MarketingCatalogToolbar.vue +6 -3
  135. package/src/pages-standard/plan-versions/PlanDiffCard.vue +16 -6
  136. package/src/pages-standard/plan-versions/PlanVersionHeader.vue +41 -25
  137. package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +45 -26
  138. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +7 -5
  139. package/src/pages-standard/plan-versions/PlanVersionsList.vue +39 -16
  140. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +24 -12
  141. package/src/pages-standard/plan-versions/format.ts +33 -17
  142. package/src/pages-standard/plans-page/PlanArchiveDialog.vue +12 -8
  143. package/src/pages-standard/plans-page/PlanBundleOverview.vue +15 -6
  144. package/src/pages-standard/plans-page/PlanDiscardDraftDialog.vue +18 -7
  145. package/src/pages-standard/plans-page/PlanPublishDialog.vue +23 -12
  146. package/src/pages-standard/tenants/format.ts +3 -2
  147. package/src/pages-tenant/MySubscriptionBundlesPage.vue +72 -37
  148. package/src/pages-tenant/PlanChangeWizard.vue +8 -4
  149. package/src/pages-tenant/TenantPlanSection.vue +17 -13
  150. package/src/pages-tenant/default-i18n.ts +217 -1
  151. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +8 -6
  152. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +9 -10
  153. package/src/pages-tenant/tenant-plan-section/TenantFeatureMatrix.vue +4 -1
  154. package/src/quasar/create-super-admin-app.ts +19 -0
  155. package/src/testing-e2e/admin-pages-suite.ts +14 -11
  156. package/src/vue/project-page-host.ts +5 -3
  157. package/src/vue/use-audit-entries.ts +3 -3
  158. package/src/vue/use-bulk-publish.ts +6 -4
  159. package/src/vue/use-bundle-versions-map.ts +6 -4
  160. package/src/vue/use-bundles.ts +13 -13
  161. package/src/vue/use-catalog-entries.ts +13 -10
  162. package/src/vue/use-discovery.ts +8 -5
  163. package/src/vue/use-entitlement.ts +3 -3
  164. package/src/vue/use-live-plan-versions.ts +4 -4
  165. package/src/vue/use-marketing-projections.ts +9 -6
  166. package/src/vue/use-nav.ts +8 -2
  167. package/src/vue/use-plan-editor.ts +2 -2
  168. package/src/vue/use-plan-versions.ts +3 -3
  169. package/src/vue/use-plans.ts +12 -12
  170. package/src/vue/use-platform-tenant-actions.ts +9 -6
  171. package/src/vue/use-promotions.ts +9 -10
  172. package/src/vue/use-subscription-draft.ts +2 -3
  173. package/src/vue/use-super-admin-context.ts +3 -3
  174. package/src/vue/use-super-admin-i18n.ts +82 -0
  175. package/src/vue/use-tenant-action-flow.ts +11 -6
  176. package/src/vue/use-tenant-manifest.ts +1 -3
  177. package/src/vue/use-tenant-subscription-bundles.ts +4 -4
  178. package/src/vue/use-tenants.ts +3 -3
  179. package/dist/action-registry-CQ2wL3R-.d.cts +0 -85
  180. package/dist/action-registry-CQ2wL3R-.d.ts +0 -85
  181. package/dist/chunk-LVGUSD3T.js +0 -26
  182. package/src/components/BusinessTypeVersionEditorDialog.vue +0 -417
  183. package/src/components/BusinessTypeVersionPublishDialog.vue +0 -258
  184. package/src/pages-standard/BusinessTypesPage.vue +0 -662
  185. package/src/pages-standard/plan-versions/VersionDiffPreview.vue +0 -167
  186. package/src/vue/use-business-types.ts +0 -269
package/dist/index.js CHANGED
@@ -6,7 +6,6 @@ import {
6
6
  BatchColumnFetcher,
7
7
  BootLoadError,
8
8
  BootLoader,
9
- DEFAULT_SECTION_ORDER,
10
9
  DEFAULT_STANDARD_PAGE_ROUTES,
11
10
  HttpJsonError,
12
11
  ManifestLoadError,
@@ -15,27 +14,41 @@ import {
15
14
  buildRoutes,
16
15
  buildSidebar,
17
16
  buildSnapshots,
17
+ defaultSectionOrder,
18
18
  getJson,
19
19
  listOpenDrafts,
20
20
  postJson,
21
21
  resolveExtension,
22
22
  trimTrailingSlashes
23
- } from "./chunk-EH7TOD4H.js";
23
+ } from "./chunk-A3W2N26K.js";
24
24
  import {
25
25
  SUPER_ADMIN_ACTIONS_KEY,
26
26
  SUPER_ADMIN_BRAND_KEY,
27
27
  SUPER_ADMIN_ENDPOINTS_KEY,
28
28
  SUPER_ADMIN_EXTENSIONS_KEY,
29
29
  SUPER_ADMIN_HTTP_KEY,
30
+ SUPER_ADMIN_I18N_KEY,
30
31
  SUPER_ADMIN_LOGIN_ADAPTER_KEY,
31
32
  SUPER_ADMIN_MANIFEST_KEY,
32
33
  SUPER_ADMIN_NOTIFY_KEY,
33
- buildNavigationGuard
34
- } from "./chunk-3YP2ZAOD.js";
34
+ buildNavigationGuard,
35
+ createSuperAdminI18n,
36
+ useSaMessages,
37
+ useSuperAdminI18n
38
+ } from "./chunk-QZOSDCNP.js";
35
39
  import {
40
+ DEFAULT_SA_LOCALE,
41
+ SA_INTL_LOCALES,
42
+ SA_LOCALES,
43
+ SA_MESSAGES,
36
44
  defaultHttpClient,
37
- defaultKvStore
38
- } from "./chunk-LVGUSD3T.js";
45
+ defaultKvStore,
46
+ defineMessages,
47
+ formatCurrency,
48
+ formatMessage,
49
+ mergeMessages,
50
+ resolveMessages
51
+ } from "./chunk-X5SQ5HMB.js";
39
52
 
40
53
  // src/vue/use-super-admin-context.ts
41
54
  import { inject } from "vue";
@@ -49,7 +62,7 @@ function useSuperAdminBrand() {
49
62
  const brand = inject(SUPER_ADMIN_BRAND_KEY);
50
63
  if (!brand) {
51
64
  throw new Error(
52
- "useSuperAdminBrand(): kein SuperAdmin-Branding im Inject-Scope. Wurde die Komponente innerhalb createSuperAdminApp() gemounted?"
65
+ "useSuperAdminBrand(): no SuperAdmin branding in inject scope. Was the component mounted inside createSuperAdminApp()?"
53
66
  );
54
67
  }
55
68
  return brand;
@@ -58,7 +71,7 @@ function useSuperAdminEndpoints() {
58
71
  const endpoints = inject(SUPER_ADMIN_ENDPOINTS_KEY);
59
72
  if (!endpoints) {
60
73
  throw new Error(
61
- "useSuperAdminEndpoints(): keine Endpoints im Inject-Scope. Wurde die Komponente innerhalb createSuperAdminApp() gemounted?"
74
+ "useSuperAdminEndpoints(): no endpoints in inject scope. Was the component mounted inside createSuperAdminApp()?"
62
75
  );
63
76
  }
64
77
  return endpoints;
@@ -71,7 +84,7 @@ function useSuperAdminLoginAdapter() {
71
84
  const adapter = inject(SUPER_ADMIN_LOGIN_ADAPTER_KEY);
72
85
  if (!adapter) {
73
86
  throw new Error(
74
- "useSuperAdminLoginAdapter(): kein Login-Adapter registriert. Reiche ihn via createSuperAdminApp({ loginAdapter }) ein."
87
+ "useSuperAdminLoginAdapter(): no login adapter registered. Pass it via createSuperAdminApp({ loginAdapter })."
75
88
  );
76
89
  }
77
90
  return adapter;
@@ -120,10 +133,10 @@ var ProjectPageHost = defineComponent({
120
133
  const cmp = resolvedComponent.value;
121
134
  if (page && cmp) return h(cmp);
122
135
  return h("div", { class: "sa-project-page-host__missing", role: "alert" }, [
123
- h("h2", "Seite nicht verf\xFCgbar"),
136
+ h("h2", "Page not available"),
124
137
  h(
125
138
  "p",
126
- page ? `componentKey "${page.componentKey}" ist nicht in der extensions:-Map registriert. Apps m\xFCssen die Komponente in createSuperAdminApp({ extensions }) eintragen.` : `Keine Manifest-Definition f\xFCr ${route.path}. Entweder fehlt die ProjectPage im Manifest, oder die Capability ist nicht aktiv.`
139
+ page ? `componentKey "${page.componentKey}" is not registered in the extensions: map. Apps must register the component in createSuperAdminApp({ extensions }).` : `No manifest definition for ${route.path}. Either the ProjectPage is missing from the manifest, or the capability is not active.`
127
140
  )
128
141
  ]);
129
142
  };
@@ -266,7 +279,7 @@ import { ref as ref2 } from "vue";
266
279
  function useTenants(options) {
267
280
  if (!options?.endpoint) {
268
281
  throw new Error(
269
- 'useTenants: `endpoint` ist Pflicht (z. B. "/api/v1/admin/tenants" oder "/api/admin/tenants"). Plattform hat keinen Default, weil Apps unterschiedliche globalPrefix-Konventionen haben.'
282
+ 'useTenants: `endpoint` is required (e.g. "/api/v1/admin/tenants" or "/api/admin/tenants"). The platform has no default because apps use different globalPrefix conventions.'
270
283
  );
271
284
  }
272
285
  const filter = options.filter ?? ref2({});
@@ -285,7 +298,7 @@ import { ref as ref3 } from "vue";
285
298
  function useAuditEntries(options) {
286
299
  if (!options?.endpoint) {
287
300
  throw new Error(
288
- 'useAuditEntries: `endpoint` ist Pflicht (z. B. "/api/admin/audit" oder "/api/v1/admin/audit"). Plattform hat keinen Default, weil Apps unterschiedliche globalPrefix-Konventionen haben.'
301
+ 'useAuditEntries: `endpoint` is required (e.g. "/api/admin/audit" or "/api/v1/admin/audit"). The platform has no default because apps use different globalPrefix conventions.'
289
302
  );
290
303
  }
291
304
  const filter = options.filter ?? ref3({});
@@ -304,7 +317,7 @@ import { ref as ref4 } from "vue";
304
317
  function useEntitlement(options) {
305
318
  if (!options?.endpoint) {
306
319
  throw new Error(
307
- 'useEntitlement: `endpoint` ist Pflicht (z. B. "/api/billing/entitlement" oder "/api/v1/billing/entitlement"). Plattform hat keinen Default, weil Apps unterschiedliche globalPrefix-Konventionen haben.'
320
+ 'useEntitlement: `endpoint` is required (e.g. "/api/billing/entitlement" or "/api/v1/billing/entitlement"). The platform has no default because apps use different globalPrefix conventions.'
308
321
  );
309
322
  }
310
323
  const endpoint = options.endpoint;
@@ -344,9 +357,7 @@ function useEntitlement(options) {
344
357
  import { ref as ref5 } from "vue";
345
358
  function useTenantManifest(options) {
346
359
  if (!options?.endpoint) {
347
- throw new Error(
348
- 'useTenantManifest: `endpoint` ist Pflicht (z. B. "/api/tenant/manifest").'
349
- );
360
+ throw new Error('useTenantManifest: `endpoint` is required (e.g. "/api/tenant/manifest").');
350
361
  }
351
362
  const http = options.http ?? defaultHttpClient();
352
363
  const manifest = ref5(null);
@@ -779,7 +790,7 @@ function useSubscriptionDraft(options) {
779
790
  }
780
791
  function toApiPayload() {
781
792
  if (!plan.value) {
782
- throw new Error("useSubscriptionDraft: plan ist nicht gesetzt");
793
+ throw new Error("useSubscriptionDraft: plan is not set");
783
794
  }
784
795
  const payload = {
785
796
  plan: plan.value,
@@ -820,7 +831,7 @@ function buildVersionsComposable(label) {
820
831
  return function(options) {
821
832
  if (!options?.endpoint) {
822
833
  throw new Error(
823
- `${label}: \`endpoint\` ist Pflicht (z. B. "/api/admin/${label}" oder "/api/v1/admin/${label}"). Plattform hat keinen Default, weil Apps unterschiedliche globalPrefix-Konventionen haben.`
834
+ `${label}: \`endpoint\` is required (e.g. "/api/admin/${label}" or "/api/v1/admin/${label}"). The platform has no default because apps use different globalPrefix conventions.`
824
835
  );
825
836
  }
826
837
  const filter = options.filter ?? ref9({});
@@ -839,9 +850,10 @@ var usePlanVersionsCatalog = buildVersionsComposable("plan-versions");
839
850
  // src/vue/use-bulk-publish.ts
840
851
  import { computed as computed3, ref as ref10 } from "vue";
841
852
  function useBulkPublish(options) {
853
+ const msg = useSaMessages("planVersions");
842
854
  if (!options?.endpoints) {
843
855
  throw new Error(
844
- "useBulkPublish: `endpoints` ist Pflicht (Mapping plan \u2192 URL-Builder). Plattform hat keinen Default, weil Apps unterschiedliche globalPrefix-Konventionen haben."
856
+ "useBulkPublish: `endpoints` is required (mapping plan \u2192 URL builder). The platform has no default because apps use different globalPrefix conventions."
845
857
  );
846
858
  }
847
859
  const http = options.http ?? defaultHttpClient();
@@ -892,7 +904,7 @@ function useBulkPublish(options) {
892
904
  if (note.length === 0) {
893
905
  for (const item of items.value) {
894
906
  item.status = "failed";
895
- item.error = "changeNote ist Pflicht beim Publish.";
907
+ item.error = msg.value.bulkPublish.changeNoteRequired;
896
908
  }
897
909
  return;
898
910
  }
@@ -916,7 +928,7 @@ import { computed as computed4, ref as ref11 } from "vue";
916
928
  var PlannedOnlyFeatureError = class extends Error {
917
929
  constructor(violations) {
918
930
  super(
919
- `Folgende Features sind im Catalog als plannedOnly markiert und d\xFCrfen nicht in einer Plan-Version stehen: ${violations.sort().join(", ")}.`
931
+ `The following features are marked as plannedOnly in the catalog and must not appear in a plan version: ${violations.sort().join(", ")}.`
920
932
  );
921
933
  this.violations = violations;
922
934
  this.name = "PlannedOnlyFeatureError";
@@ -1021,9 +1033,10 @@ var DiscoveryLoadError = class extends Error {
1021
1033
  status;
1022
1034
  };
1023
1035
  function useDiscovery(options) {
1036
+ const msg = useSaMessages("discovery");
1024
1037
  if (!options?.endpoint) {
1025
1038
  throw new Error(
1026
- 'useDiscovery: `endpoint` ist Pflicht (z. B. "/api/admin/discovery" oder "/api/v1/admin/discovery"). Plattform hat keinen Default, weil Apps unterschiedliche globalPrefix-Konventionen haben.'
1039
+ 'useDiscovery: `endpoint` is required (e.g. "/api/admin/discovery" or "/api/v1/admin/discovery"). The platform has no default because apps use different globalPrefix conventions.'
1027
1040
  );
1028
1041
  }
1029
1042
  const http = options.http ?? defaultHttpClient();
@@ -1048,7 +1061,7 @@ function useDiscovery(options) {
1048
1061
  if (res.status !== 200) {
1049
1062
  throw new DiscoveryLoadError(
1050
1063
  res.status,
1051
- `Discovery-Endpoint antwortete mit HTTP ${res.status}`
1064
+ formatMessage(msg.value.errorDiscoveryHttp, { status: res.status })
1052
1065
  );
1053
1066
  }
1054
1067
  const body = await res.json();
@@ -1078,7 +1091,7 @@ function useDiscovery(options) {
1078
1091
  if (res.status !== 200 && res.status !== 201) {
1079
1092
  throw new DiscoveryLoadError(
1080
1093
  res.status,
1081
- `Discovery-Rescan antwortete mit HTTP ${res.status}`
1094
+ formatMessage(msg.value.errorRescanHttp, { status: res.status })
1082
1095
  );
1083
1096
  }
1084
1097
  const body = await res.json();
@@ -1110,11 +1123,12 @@ var CatalogEntriesApiError = class extends Error {
1110
1123
  };
1111
1124
  function useCatalogEntries(options) {
1112
1125
  if (!options?.adminEndpoint) {
1113
- throw new Error("useCatalogEntries: `adminEndpoint` ist Pflicht.");
1126
+ throw new Error("useCatalogEntries: `adminEndpoint` is required.");
1114
1127
  }
1115
1128
  if (!options?.projectKey) {
1116
- throw new Error("useCatalogEntries: `projectKey` ist Pflicht.");
1129
+ throw new Error("useCatalogEntries: `projectKey` is required.");
1117
1130
  }
1131
+ const msg = useSaMessages("discovery");
1118
1132
  const http = options.http ?? defaultHttpClient();
1119
1133
  const capabilities = ref14([]);
1120
1134
  const features = ref14([]);
@@ -1139,7 +1153,7 @@ function useCatalogEntries(options) {
1139
1153
  throw new CatalogEntriesApiError(
1140
1154
  res.status,
1141
1155
  body,
1142
- `Catalog-Entries-API antwortete mit HTTP ${res.status}`
1156
+ formatMessage(msg.value.errorCatalogHttp, { status: res.status })
1143
1157
  );
1144
1158
  }
1145
1159
  return body;
@@ -1167,7 +1181,7 @@ function useCatalogEntries(options) {
1167
1181
  `${base}/features/${encodeURIComponent(featureKey)}/review?projectKey=${pk}`,
1168
1182
  { method: "PATCH", body: JSON.stringify(data) }
1169
1183
  );
1170
- if (!updated) throw new CatalogEntriesApiError(0, null, "Review gab keinen Body zur\xFCck");
1184
+ if (!updated) throw new CatalogEntriesApiError(0, null, "Review returned no body");
1171
1185
  features.value = features.value.map((f) => f.featureKey === featureKey ? updated : f);
1172
1186
  return updated;
1173
1187
  }
@@ -1176,7 +1190,7 @@ function useCatalogEntries(options) {
1176
1190
  `${base}/quotas/${encodeURIComponent(quotaKey)}/review?projectKey=${pk}`,
1177
1191
  { method: "PATCH", body: JSON.stringify(data) }
1178
1192
  );
1179
- if (!updated) throw new CatalogEntriesApiError(0, null, "Review gab keinen Body zur\xFCck");
1193
+ if (!updated) throw new CatalogEntriesApiError(0, null, "Review returned no body");
1180
1194
  quotas.value = quotas.value.map((q) => q.quotaKey === quotaKey ? updated : q);
1181
1195
  return updated;
1182
1196
  }
@@ -1185,7 +1199,7 @@ function useCatalogEntries(options) {
1185
1199
  `${base}/features/${encodeURIComponent(featureKey)}/i18n?projectKey=${pk}`,
1186
1200
  { method: "PATCH", body: JSON.stringify({ i18n }) }
1187
1201
  );
1188
- if (!updated) throw new CatalogEntriesApiError(0, null, "i18n gab keinen Body zur\xFCck");
1202
+ if (!updated) throw new CatalogEntriesApiError(0, null, "i18n returned no body");
1189
1203
  features.value = features.value.map((f) => f.featureKey === featureKey ? updated : f);
1190
1204
  return updated;
1191
1205
  }
@@ -1194,7 +1208,7 @@ function useCatalogEntries(options) {
1194
1208
  `${base}/quotas/${encodeURIComponent(quotaKey)}/i18n?projectKey=${pk}`,
1195
1209
  { method: "PATCH", body: JSON.stringify({ i18n }) }
1196
1210
  );
1197
- if (!updated) throw new CatalogEntriesApiError(0, null, "i18n gab keinen Body zur\xFCck");
1211
+ if (!updated) throw new CatalogEntriesApiError(0, null, "i18n returned no body");
1198
1212
  quotas.value = quotas.value.map((q) => q.quotaKey === quotaKey ? updated : q);
1199
1213
  return updated;
1200
1214
  }
@@ -1203,7 +1217,7 @@ function useCatalogEntries(options) {
1203
1217
  `${base}/features/${encodeURIComponent(featureKey)}?projectKey=${pk}`,
1204
1218
  { method: "PATCH", body: JSON.stringify(data) }
1205
1219
  );
1206
- if (!updated) throw new CatalogEntriesApiError(0, null, "Base gab keinen Body zur\xFCck");
1220
+ if (!updated) throw new CatalogEntriesApiError(0, null, "Base returned no body");
1207
1221
  features.value = features.value.map((f) => f.featureKey === featureKey ? updated : f);
1208
1222
  return updated;
1209
1223
  }
@@ -1212,7 +1226,7 @@ function useCatalogEntries(options) {
1212
1226
  `${base}/quotas/${encodeURIComponent(quotaKey)}?projectKey=${pk}`,
1213
1227
  { method: "PATCH", body: JSON.stringify(data) }
1214
1228
  );
1215
- if (!updated) throw new CatalogEntriesApiError(0, null, "Base gab keinen Body zur\xFCck");
1229
+ if (!updated) throw new CatalogEntriesApiError(0, null, "Base returned no body");
1216
1230
  quotas.value = quotas.value.map((q) => q.quotaKey === quotaKey ? updated : q);
1217
1231
  return updated;
1218
1232
  }
@@ -1221,7 +1235,7 @@ function useCatalogEntries(options) {
1221
1235
  method: "POST",
1222
1236
  body: JSON.stringify({ snapshot })
1223
1237
  });
1224
- if (!result) throw new CatalogEntriesApiError(0, null, "Sync gab keinen Body zur\xFCck");
1238
+ if (!result) throw new CatalogEntriesApiError(0, null, "Sync returned no body");
1225
1239
  await load();
1226
1240
  return result;
1227
1241
  }
@@ -1260,11 +1274,11 @@ var BundlesApiError = class extends Error {
1260
1274
  function useBundles(options) {
1261
1275
  if (!options?.adminEndpoint) {
1262
1276
  throw new Error(
1263
- 'useBundles: `adminEndpoint` ist Pflicht (z. B. "/api/admin" oder "/api/v1/admin"). Plattform hat keinen Default, weil Apps unterschiedliche globalPrefix-Konventionen haben.'
1277
+ 'useBundles: `adminEndpoint` is required (e.g. "/api/admin" or "/api/v1/admin"). The platform has no default, because apps use different globalPrefix conventions.'
1264
1278
  );
1265
1279
  }
1266
1280
  if (!options?.projectKey) {
1267
- throw new Error("useBundles: `projectKey` ist Pflicht.");
1281
+ throw new Error("useBundles: `projectKey` is required.");
1268
1282
  }
1269
1283
  const http = options.http ?? defaultHttpClient();
1270
1284
  const bundles = ref15([]);
@@ -1287,7 +1301,7 @@ function useBundles(options) {
1287
1301
  throw new BundlesApiError(
1288
1302
  res.status,
1289
1303
  body,
1290
- `Bundles-API antwortete mit HTTP ${res.status}`
1304
+ `Bundles API responded with HTTP ${res.status}`
1291
1305
  );
1292
1306
  }
1293
1307
  return body;
@@ -1311,7 +1325,7 @@ function useBundles(options) {
1311
1325
  method: "POST",
1312
1326
  body: JSON.stringify(data)
1313
1327
  });
1314
- if (!created) throw new BundlesApiError(0, null, "Create gab keinen Body zur\xFCck");
1328
+ if (!created) throw new BundlesApiError(0, null, "Create returned no body");
1315
1329
  bundles.value = [...bundles.value, created];
1316
1330
  return created;
1317
1331
  }
@@ -1320,7 +1334,7 @@ function useBundles(options) {
1320
1334
  method: "PATCH",
1321
1335
  body: JSON.stringify(data)
1322
1336
  });
1323
- if (!updated) throw new BundlesApiError(0, null, "Update gab keinen Body zur\xFCck");
1337
+ if (!updated) throw new BundlesApiError(0, null, "Update returned no body");
1324
1338
  bundles.value = bundles.value.map((b) => b.id === bundleId ? updated : b);
1325
1339
  return updated;
1326
1340
  }
@@ -1335,10 +1349,10 @@ function useBundles(options) {
1335
1349
  }
1336
1350
  function useBundleVersions(options) {
1337
1351
  if (!options?.adminEndpoint) {
1338
- throw new Error("useBundleVersions: `adminEndpoint` ist Pflicht.");
1352
+ throw new Error("useBundleVersions: `adminEndpoint` is required.");
1339
1353
  }
1340
1354
  if (!options?.bundleId) {
1341
- throw new Error("useBundleVersions: `bundleId` ist Pflicht.");
1355
+ throw new Error("useBundleVersions: `bundleId` is required.");
1342
1356
  }
1343
1357
  const http = options.http ?? defaultHttpClient();
1344
1358
  const versions = ref15([]);
@@ -1362,7 +1376,7 @@ function useBundleVersions(options) {
1362
1376
  throw new BundlesApiError(
1363
1377
  res.status,
1364
1378
  body,
1365
- `BundleVersions-API antwortete mit HTTP ${res.status}`
1379
+ `BundleVersions API responded with HTTP ${res.status}`
1366
1380
  );
1367
1381
  }
1368
1382
  return body;
@@ -1384,7 +1398,7 @@ function useBundleVersions(options) {
1384
1398
  method: "POST",
1385
1399
  body: JSON.stringify(data)
1386
1400
  });
1387
- if (!result) throw new BundlesApiError(0, null, "CreateDraft gab keinen Body zur\xFCck");
1401
+ if (!result) throw new BundlesApiError(0, null, "CreateDraft returned no body");
1388
1402
  versions.value = [...versions.value, result.bundleVersion];
1389
1403
  return result;
1390
1404
  }
@@ -1393,7 +1407,7 @@ function useBundleVersions(options) {
1393
1407
  `${versionUrlBase}/${versionId}`,
1394
1408
  { method: "PATCH", body: JSON.stringify(data) }
1395
1409
  );
1396
- if (!result) throw new BundlesApiError(0, null, "UpdateDraft gab keinen Body zur\xFCck");
1410
+ if (!result) throw new BundlesApiError(0, null, "UpdateDraft returned no body");
1397
1411
  versions.value = versions.value.map((v) => v.id === versionId ? result.bundleVersion : v);
1398
1412
  return result;
1399
1413
  }
@@ -1402,7 +1416,7 @@ function useBundleVersions(options) {
1402
1416
  `${versionUrlBase}/${versionId}/publish`,
1403
1417
  { method: "POST", body: JSON.stringify(opts) }
1404
1418
  );
1405
- if (!result) throw new BundlesApiError(0, null, "Publish gab keinen Body zur\xFCck");
1419
+ if (!result) throw new BundlesApiError(0, null, "Publish returned no body");
1406
1420
  await load();
1407
1421
  return result;
1408
1422
  }
@@ -1420,10 +1434,10 @@ function useBundleVersions(options) {
1420
1434
  import { ref as ref16, watch as watch2 } from "vue";
1421
1435
  function useBundleVersionsMap(options) {
1422
1436
  if (!options?.adminEndpoint) {
1423
- throw new Error("useBundleVersionsMap: `adminEndpoint` ist Pflicht.");
1437
+ throw new Error("useBundleVersionsMap: `adminEndpoint` is required.");
1424
1438
  }
1425
1439
  if (!options?.bundles) {
1426
- throw new Error("useBundleVersionsMap: `bundles` ist Pflicht.");
1440
+ throw new Error("useBundleVersionsMap: `bundles` is required.");
1427
1441
  }
1428
1442
  const http = options.http ?? defaultHttpClient();
1429
1443
  const versionsByBundle = ref16({});
@@ -1439,7 +1453,9 @@ function useBundleVersionsMap(options) {
1439
1453
  headers: { "content-type": "application/json", ...authHeaders() }
1440
1454
  });
1441
1455
  if (res.status >= 400) {
1442
- throw new Error(`HTTP ${res.status} beim Laden der Versionen f\xFCr Bundle '${bundleId}'`);
1456
+ throw new Error(
1457
+ `HTTP ${res.status} while loading the versions for bundle '${bundleId}'`
1458
+ );
1443
1459
  }
1444
1460
  return await res.json().catch(() => null) ?? [];
1445
1461
  }
@@ -1454,7 +1470,7 @@ function useBundleVersionsMap(options) {
1454
1470
  return [b.id, versions];
1455
1471
  } catch (err) {
1456
1472
  console.warn(
1457
- `useBundleVersionsMap: Bundle '${b.bundleKey}' Versions-Load failed`,
1473
+ `useBundleVersionsMap: loading versions for bundle '${b.bundleKey}' failed`,
1458
1474
  err
1459
1475
  );
1460
1476
  return [b.id, []];
@@ -1502,7 +1518,7 @@ var TenantSubscriptionBundlesApiError = class extends Error {
1502
1518
  function useTenantSubscriptionBundles(options) {
1503
1519
  if (!options?.billingEndpoint) {
1504
1520
  throw new Error(
1505
- 'useTenantSubscriptionBundles: `billingEndpoint` ist Pflicht (z. B. "/api/v1").'
1521
+ 'useTenantSubscriptionBundles: `billingEndpoint` is required (e.g. "/api/v1").'
1506
1522
  );
1507
1523
  }
1508
1524
  const http = options.http ?? defaultHttpClient();
@@ -1526,7 +1542,7 @@ function useTenantSubscriptionBundles(options) {
1526
1542
  throw new TenantSubscriptionBundlesApiError(
1527
1543
  res.status,
1528
1544
  body,
1529
- `SubscriptionBundle-API antwortete mit HTTP ${res.status}`
1545
+ `SubscriptionBundle API responded with HTTP ${res.status}`
1530
1546
  );
1531
1547
  }
1532
1548
  return body;
@@ -1549,7 +1565,7 @@ function useTenantSubscriptionBundles(options) {
1549
1565
  body: JSON.stringify(data)
1550
1566
  });
1551
1567
  if (!result) {
1552
- throw new TenantSubscriptionBundlesApiError(0, null, "add gab keinen Body zur\xFCck");
1568
+ throw new TenantSubscriptionBundlesApiError(0, null, "add returned no body");
1553
1569
  }
1554
1570
  const hydrated = rehydrateDates(result);
1555
1571
  bundles.value = [hydrated, ...bundles.value];
@@ -1561,7 +1577,7 @@ function useTenantSubscriptionBundles(options) {
1561
1577
  { method: "DELETE", body: JSON.stringify(opts) }
1562
1578
  );
1563
1579
  if (!result) {
1564
- throw new TenantSubscriptionBundlesApiError(0, null, "cancel gab keinen Body zur\xFCck");
1580
+ throw new TenantSubscriptionBundlesApiError(0, null, "cancel returned no body");
1565
1581
  }
1566
1582
  const hydrated = rehydrateDates(result);
1567
1583
  bundles.value = bundles.value.map((b) => b.id === subscriptionBundleId ? hydrated : b);
@@ -1582,177 +1598,8 @@ function rehydrateDates(raw) {
1582
1598
  };
1583
1599
  }
1584
1600
 
1585
- // src/vue/use-business-types.ts
1586
- import { ref as ref18 } from "vue";
1587
- var BusinessTypesApiError = class extends Error {
1588
- constructor(status, body, message) {
1589
- super(message);
1590
- this.status = status;
1591
- this.body = body;
1592
- this.name = "BusinessTypesApiError";
1593
- }
1594
- status;
1595
- body;
1596
- };
1597
- function useBusinessTypes(options) {
1598
- if (!options?.adminEndpoint) {
1599
- throw new Error("useBusinessTypes: `adminEndpoint` ist Pflicht.");
1600
- }
1601
- if (!options?.projectKey) {
1602
- throw new Error("useBusinessTypes: `projectKey` ist Pflicht.");
1603
- }
1604
- const http = options.http ?? defaultHttpClient();
1605
- const businessTypes = ref18([]);
1606
- const loading = ref18(false);
1607
- const error = ref18(null);
1608
- const baseUrl = `${options.adminEndpoint}/catalog/business-types`;
1609
- function authHeaders() {
1610
- const token = options.getAuthToken?.();
1611
- return token ? { Authorization: `Bearer ${token}` } : {};
1612
- }
1613
- async function fetchJson(url, init) {
1614
- const res = await http(url, {
1615
- method: init?.method ?? "GET",
1616
- headers: { "content-type": "application/json", ...authHeaders(), ...init?.headers },
1617
- body: init?.body
1618
- });
1619
- if (res.status === 204) return null;
1620
- const body = await res.json().catch(() => null);
1621
- if (res.status >= 400) {
1622
- throw new BusinessTypesApiError(
1623
- res.status,
1624
- body,
1625
- `BusinessTypes-API antwortete mit HTTP ${res.status}`
1626
- );
1627
- }
1628
- return body;
1629
- }
1630
- async function load() {
1631
- loading.value = true;
1632
- error.value = null;
1633
- try {
1634
- const data = await fetchJson(
1635
- `${baseUrl}?projectKey=${encodeURIComponent(options.projectKey)}`
1636
- );
1637
- businessTypes.value = data ?? [];
1638
- } catch (err) {
1639
- error.value = err instanceof Error ? err : new Error(String(err));
1640
- } finally {
1641
- loading.value = false;
1642
- }
1643
- }
1644
- async function create(data) {
1645
- const created = await fetchJson(baseUrl, {
1646
- method: "POST",
1647
- body: JSON.stringify(data)
1648
- });
1649
- if (!created) throw new BusinessTypesApiError(0, null, "Create gab keinen Body zur\xFCck");
1650
- businessTypes.value = [...businessTypes.value, created];
1651
- return created;
1652
- }
1653
- async function update(businessTypeId, data) {
1654
- const updated = await fetchJson(`${baseUrl}/${businessTypeId}`, {
1655
- method: "PATCH",
1656
- body: JSON.stringify(data)
1657
- });
1658
- if (!updated) throw new BusinessTypesApiError(0, null, "Update gab keinen Body zur\xFCck");
1659
- businessTypes.value = businessTypes.value.map(
1660
- (b) => b.id === businessTypeId ? updated : b
1661
- );
1662
- return updated;
1663
- }
1664
- async function softDelete(businessTypeId) {
1665
- await fetchJson(`${baseUrl}/${businessTypeId}`, { method: "DELETE" });
1666
- businessTypes.value = businessTypes.value.filter((b) => b.id !== businessTypeId);
1667
- }
1668
- if (options.autoLoad) {
1669
- void load();
1670
- }
1671
- return { businessTypes, loading, error, load, create, update, softDelete };
1672
- }
1673
- function useBusinessTypeVersions(options) {
1674
- if (!options?.adminEndpoint) {
1675
- throw new Error("useBusinessTypeVersions: `adminEndpoint` ist Pflicht.");
1676
- }
1677
- if (!options?.businessTypeId) {
1678
- throw new Error("useBusinessTypeVersions: `businessTypeId` ist Pflicht.");
1679
- }
1680
- const http = options.http ?? defaultHttpClient();
1681
- const versions = ref18([]);
1682
- const loading = ref18(false);
1683
- const error = ref18(null);
1684
- const versionsUrl = `${options.adminEndpoint}/catalog/business-types/${options.businessTypeId}/versions`;
1685
- const versionUrlBase = `${options.adminEndpoint}/catalog/business-type-versions`;
1686
- function authHeaders() {
1687
- const token = options.getAuthToken?.();
1688
- return token ? { Authorization: `Bearer ${token}` } : {};
1689
- }
1690
- async function fetchJson(url, init) {
1691
- const res = await http(url, {
1692
- method: init?.method ?? "GET",
1693
- headers: { "content-type": "application/json", ...authHeaders(), ...init?.headers },
1694
- body: init?.body
1695
- });
1696
- if (res.status === 204) return null;
1697
- const body = await res.json().catch(() => null);
1698
- if (res.status >= 400) {
1699
- throw new BusinessTypesApiError(
1700
- res.status,
1701
- body,
1702
- `BusinessTypeVersions-API antwortete mit HTTP ${res.status}`
1703
- );
1704
- }
1705
- return body;
1706
- }
1707
- async function load() {
1708
- loading.value = true;
1709
- error.value = null;
1710
- try {
1711
- const data = await fetchJson(versionsUrl);
1712
- versions.value = data ?? [];
1713
- } catch (err) {
1714
- error.value = err instanceof Error ? err : new Error(String(err));
1715
- } finally {
1716
- loading.value = false;
1717
- }
1718
- }
1719
- async function createDraft(data) {
1720
- const result = await fetchJson(versionsUrl, {
1721
- method: "POST",
1722
- body: JSON.stringify(data)
1723
- });
1724
- if (!result) throw new BusinessTypesApiError(0, null, "CreateDraft gab keinen Body zur\xFCck");
1725
- versions.value = [...versions.value, result.businessTypeVersion];
1726
- return result;
1727
- }
1728
- async function updateDraft(versionId, data) {
1729
- const result = await fetchJson(
1730
- `${versionUrlBase}/${versionId}`,
1731
- { method: "PATCH", body: JSON.stringify(data) }
1732
- );
1733
- if (!result) throw new BusinessTypesApiError(0, null, "UpdateDraft gab keinen Body zur\xFCck");
1734
- versions.value = versions.value.map(
1735
- (v) => v.id === versionId ? result.businessTypeVersion : v
1736
- );
1737
- return result;
1738
- }
1739
- async function publish(versionId, opts = {}) {
1740
- const result = await fetchJson(
1741
- `${versionUrlBase}/${versionId}/publish`,
1742
- { method: "POST", body: JSON.stringify(opts) }
1743
- );
1744
- if (!result) throw new BusinessTypesApiError(0, null, "Publish gab keinen Body zur\xFCck");
1745
- await load();
1746
- return result;
1747
- }
1748
- if (options.autoLoad) {
1749
- void load();
1750
- }
1751
- return { versions, loading, error, load, createDraft, updateDraft, publish };
1752
- }
1753
-
1754
1601
  // src/vue/use-marketing-projections.ts
1755
- import { ref as ref19 } from "vue";
1602
+ import { ref as ref18 } from "vue";
1756
1603
  var MarketingProjectionsApiError = class extends Error {
1757
1604
  constructor(status, body, message) {
1758
1605
  super(message);
@@ -1765,16 +1612,17 @@ var MarketingProjectionsApiError = class extends Error {
1765
1612
  };
1766
1613
  function useMarketingProjections(options) {
1767
1614
  if (!options?.adminEndpoint) {
1768
- throw new Error("useMarketingProjections: `adminEndpoint` ist Pflicht.");
1615
+ throw new Error("useMarketingProjections: `adminEndpoint` is required.");
1769
1616
  }
1770
1617
  if (!options?.filter?.projectKey) {
1771
- throw new Error("useMarketingProjections: `filter.projectKey` ist Pflicht.");
1618
+ throw new Error("useMarketingProjections: `filter.projectKey` is required.");
1772
1619
  }
1620
+ const msg = useSaMessages("marketing");
1773
1621
  const http = options.http ?? defaultHttpClient();
1774
- const projections = ref19([]);
1775
- const filter = ref19({ ...options.filter });
1776
- const loading = ref19(false);
1777
- const error = ref19(null);
1622
+ const projections = ref18([]);
1623
+ const filter = ref18({ ...options.filter });
1624
+ const loading = ref18(false);
1625
+ const error = ref18(null);
1778
1626
  const baseUrl = `${options.adminEndpoint}/catalog/marketing-projections`;
1779
1627
  function authHeaders() {
1780
1628
  const token = options.getAuthToken?.();
@@ -1801,7 +1649,7 @@ function useMarketingProjections(options) {
1801
1649
  throw new MarketingProjectionsApiError(
1802
1650
  res.status,
1803
1651
  body,
1804
- `MarketingProjections-API antwortete mit HTTP ${res.status}`
1652
+ formatMessage(msg.value.errors.projectionsApi, { status: res.status })
1805
1653
  );
1806
1654
  }
1807
1655
  return body;
@@ -1828,7 +1676,7 @@ function useMarketingProjections(options) {
1828
1676
  body: JSON.stringify(data)
1829
1677
  });
1830
1678
  if (!created) {
1831
- throw new MarketingProjectionsApiError(0, null, "Create gab keinen Body zur\xFCck");
1679
+ throw new MarketingProjectionsApiError(0, null, "Create returned no body");
1832
1680
  }
1833
1681
  await load();
1834
1682
  return created;
@@ -1839,7 +1687,7 @@ function useMarketingProjections(options) {
1839
1687
  body: JSON.stringify(data)
1840
1688
  });
1841
1689
  if (!updated) {
1842
- throw new MarketingProjectionsApiError(0, null, "Update gab keinen Body zur\xFCck");
1690
+ throw new MarketingProjectionsApiError(0, null, "Update returned no body");
1843
1691
  }
1844
1692
  projections.value = projections.value.map((p) => p.id === id ? updated : p);
1845
1693
  return updated;
@@ -1855,7 +1703,7 @@ function useMarketingProjections(options) {
1855
1703
  }
1856
1704
 
1857
1705
  // src/vue/use-promotions.ts
1858
- import { ref as ref20 } from "vue";
1706
+ import { ref as ref19 } from "vue";
1859
1707
  var PromotionsApiError = class extends Error {
1860
1708
  constructor(status, body, message) {
1861
1709
  super(message);
@@ -1868,15 +1716,16 @@ var PromotionsApiError = class extends Error {
1868
1716
  };
1869
1717
  function usePromotions(options) {
1870
1718
  if (!options?.adminEndpoint) {
1871
- throw new Error("usePromotions: `adminEndpoint` ist Pflicht.");
1719
+ throw new Error("usePromotions: `adminEndpoint` is required.");
1872
1720
  }
1873
1721
  if (!options?.projectKey) {
1874
- throw new Error("usePromotions: `projectKey` ist Pflicht.");
1722
+ throw new Error("usePromotions: `projectKey` is required.");
1875
1723
  }
1724
+ const msg = useSaMessages("promos");
1876
1725
  const http = options.http ?? defaultHttpClient();
1877
- const promotions = ref20([]);
1878
- const loading = ref20(false);
1879
- const error = ref20(null);
1726
+ const promotions = ref19([]);
1727
+ const loading = ref19(false);
1728
+ const error = ref19(null);
1880
1729
  const baseUrl = `${options.adminEndpoint}/catalog/promotions`;
1881
1730
  const pk = encodeURIComponent(options.projectKey);
1882
1731
  function authHeaders() {
@@ -1895,7 +1744,7 @@ function usePromotions(options) {
1895
1744
  throw new PromotionsApiError(
1896
1745
  res.status,
1897
1746
  body,
1898
- `Promotions-API antwortete mit HTTP ${res.status}`
1747
+ formatMessage(msg.value.apiErrorHttpStatus, { status: res.status })
1899
1748
  );
1900
1749
  }
1901
1750
  return body;
@@ -1917,7 +1766,7 @@ function usePromotions(options) {
1917
1766
  method: "POST",
1918
1767
  body: JSON.stringify(data)
1919
1768
  });
1920
- if (!created) throw new PromotionsApiError(0, null, "Create gab keinen Body zur\xFCck");
1769
+ if (!created) throw new PromotionsApiError(0, null, "Create returned no body");
1921
1770
  promotions.value = [...promotions.value, created];
1922
1771
  return created;
1923
1772
  }
@@ -1926,7 +1775,7 @@ function usePromotions(options) {
1926
1775
  method: "PATCH",
1927
1776
  body: JSON.stringify(data)
1928
1777
  });
1929
- if (!updated) throw new PromotionsApiError(0, null, "Update gab keinen Body zur\xFCck");
1778
+ if (!updated) throw new PromotionsApiError(0, null, "Update returned no body");
1930
1779
  promotions.value = promotions.value.map((p) => p.id === id ? updated : p);
1931
1780
  return updated;
1932
1781
  }
@@ -1941,7 +1790,7 @@ function usePromotions(options) {
1941
1790
  }
1942
1791
 
1943
1792
  // src/vue/use-plans.ts
1944
- import { ref as ref21 } from "vue";
1793
+ import { ref as ref20 } from "vue";
1945
1794
  var PlansApiError = class extends Error {
1946
1795
  constructor(status, body, message) {
1947
1796
  super(message);
@@ -1955,17 +1804,17 @@ var PlansApiError = class extends Error {
1955
1804
  function usePlans(options) {
1956
1805
  if (!options?.adminEndpoint) {
1957
1806
  throw new Error(
1958
- 'usePlans: `adminEndpoint` ist Pflicht (z. B. "/api/admin" oder "/api/v1/admin").'
1807
+ 'usePlans: `adminEndpoint` is required (e.g. "/api/admin" or "/api/v1/admin").'
1959
1808
  );
1960
1809
  }
1961
1810
  if (!options?.projectKey) {
1962
- throw new Error("usePlans: `projectKey` ist Pflicht.");
1811
+ throw new Error("usePlans: `projectKey` is required.");
1963
1812
  }
1964
1813
  const http = options.http ?? defaultHttpClient();
1965
- const plans = ref21([]);
1966
- const loading = ref21(false);
1967
- const error = ref21(null);
1968
- const tenantCountsByPlanKey = ref21({});
1814
+ const plans = ref20([]);
1815
+ const loading = ref20(false);
1816
+ const error = ref20(null);
1817
+ const tenantCountsByPlanKey = ref20({});
1969
1818
  const baseUrl = `${options.adminEndpoint}/catalog/plans`;
1970
1819
  function authHeaders() {
1971
1820
  const token = options.getAuthToken?.();
@@ -1987,7 +1836,7 @@ function usePlans(options) {
1987
1836
  throw new PlansApiError(
1988
1837
  res.status,
1989
1838
  body,
1990
- `Plans-API antwortete mit HTTP ${res.status}`
1839
+ `Plans API responded with HTTP ${res.status}`
1991
1840
  );
1992
1841
  }
1993
1842
  return body;
@@ -2021,7 +1870,7 @@ function usePlans(options) {
2021
1870
  method: "POST",
2022
1871
  body: JSON.stringify(data)
2023
1872
  });
2024
- if (!created) throw new PlansApiError(0, null, "Create gab keinen Body zur\xFCck");
1873
+ if (!created) throw new PlansApiError(0, null, "Create returned no body");
2025
1874
  plans.value = [...plans.value, created];
2026
1875
  return created;
2027
1876
  }
@@ -2030,7 +1879,7 @@ function usePlans(options) {
2030
1879
  method: "PATCH",
2031
1880
  body: JSON.stringify(data)
2032
1881
  });
2033
- if (!updated) throw new PlansApiError(0, null, "Update gab keinen Body zur\xFCck");
1882
+ if (!updated) throw new PlansApiError(0, null, "Update returned no body");
2034
1883
  plans.value = plans.value.map((p) => p.id === planId ? updated : p);
2035
1884
  return updated;
2036
1885
  }
@@ -2060,15 +1909,15 @@ function usePlans(options) {
2060
1909
  }
2061
1910
  function usePlanVersions(options) {
2062
1911
  if (!options?.adminEndpoint) {
2063
- throw new Error("usePlanVersions: `adminEndpoint` ist Pflicht.");
1912
+ throw new Error("usePlanVersions: `adminEndpoint` is required.");
2064
1913
  }
2065
1914
  if (!options?.planId) {
2066
- throw new Error("usePlanVersions: `planId` ist Pflicht.");
1915
+ throw new Error("usePlanVersions: `planId` is required.");
2067
1916
  }
2068
1917
  const http = options.http ?? defaultHttpClient();
2069
- const versions = ref21([]);
2070
- const loading = ref21(false);
2071
- const error = ref21(null);
1918
+ const versions = ref20([]);
1919
+ const loading = ref20(false);
1920
+ const error = ref20(null);
2072
1921
  const planVersionsUrl = `${options.adminEndpoint}/catalog/plans/${options.planId}/versions`;
2073
1922
  const versionUrlBase = `${options.adminEndpoint}/catalog/plan-versions`;
2074
1923
  function authHeaders() {
@@ -2091,7 +1940,7 @@ function usePlanVersions(options) {
2091
1940
  throw new PlansApiError(
2092
1941
  res.status,
2093
1942
  body,
2094
- `PlanVersions-API antwortete mit HTTP ${res.status}`
1943
+ `PlanVersions API responded with HTTP ${res.status}`
2095
1944
  );
2096
1945
  }
2097
1946
  return body;
@@ -2113,7 +1962,7 @@ function usePlanVersions(options) {
2113
1962
  method: "POST",
2114
1963
  body: JSON.stringify(data)
2115
1964
  });
2116
- if (!result) throw new PlansApiError(0, null, "CreateDraft gab keinen Body zur\xFCck");
1965
+ if (!result) throw new PlansApiError(0, null, "CreateDraft returned no body");
2117
1966
  versions.value = [...versions.value, result.planVersion];
2118
1967
  return result;
2119
1968
  }
@@ -2122,7 +1971,7 @@ function usePlanVersions(options) {
2122
1971
  `${versionUrlBase}/${versionId}`,
2123
1972
  { method: "PATCH", body: JSON.stringify(data) }
2124
1973
  );
2125
- if (!result) throw new PlansApiError(0, null, "UpdateDraft gab keinen Body zur\xFCck");
1974
+ if (!result) throw new PlansApiError(0, null, "UpdateDraft returned no body");
2126
1975
  versions.value = versions.value.map((v) => v.id === versionId ? result.planVersion : v);
2127
1976
  return result;
2128
1977
  }
@@ -2131,7 +1980,7 @@ function usePlanVersions(options) {
2131
1980
  `${versionUrlBase}/${versionId}/publish`,
2132
1981
  { method: "POST", body: JSON.stringify(opts) }
2133
1982
  );
2134
- if (!result) throw new PlansApiError(0, null, "Publish gab keinen Body zur\xFCck");
1983
+ if (!result) throw new PlansApiError(0, null, "Publish returned no body");
2135
1984
  versions.value = versions.value.map((v) => v.id === versionId ? result.planVersion : v);
2136
1985
  return result;
2137
1986
  }
@@ -2144,7 +1993,7 @@ function usePlanVersions(options) {
2144
1993
  `${versionUrlBase}/${versionId}/terminate`,
2145
1994
  { method: "POST", body: JSON.stringify({ endsAt }) }
2146
1995
  );
2147
- if (!updated) throw new PlansApiError(0, null, "Terminate gab keinen Body zur\xFCck");
1996
+ if (!updated) throw new PlansApiError(0, null, "Terminate returned no body");
2148
1997
  versions.value = versions.value.map((v) => v.id === versionId ? updated : v);
2149
1998
  return updated;
2150
1999
  }
@@ -2165,18 +2014,18 @@ function usePlanVersions(options) {
2165
2014
  }
2166
2015
 
2167
2016
  // src/vue/use-live-plan-versions.ts
2168
- import { ref as ref22, watch as watch3 } from "vue";
2017
+ import { ref as ref21, watch as watch3 } from "vue";
2169
2018
  function useLivePlanVersions(options) {
2170
2019
  if (!options?.adminEndpoint) {
2171
- throw new Error("useLivePlanVersions: `adminEndpoint` ist Pflicht.");
2020
+ throw new Error("useLivePlanVersions: `adminEndpoint` is required.");
2172
2021
  }
2173
2022
  if (!options?.plans) {
2174
- throw new Error("useLivePlanVersions: `plans` ist Pflicht.");
2023
+ throw new Error("useLivePlanVersions: `plans` is required.");
2175
2024
  }
2176
2025
  const http = options.http ?? defaultHttpClient();
2177
- const livePlanVersions = ref22({});
2178
- const loading = ref22(false);
2179
- const error = ref22(null);
2026
+ const livePlanVersions = ref21({});
2027
+ const loading = ref21(false);
2028
+ const error = ref21(null);
2180
2029
  function authHeaders() {
2181
2030
  const token = options.getAuthToken?.();
2182
2031
  return token ? { Authorization: `Bearer ${token}` } : {};
@@ -2187,7 +2036,7 @@ function useLivePlanVersions(options) {
2187
2036
  headers: { "content-type": "application/json", ...authHeaders() }
2188
2037
  });
2189
2038
  if (res.status >= 400) {
2190
- throw new Error(`HTTP ${res.status} beim Laden der Versionen f\xFCr Plan '${planId}'`);
2039
+ throw new Error(`HTTP ${res.status} while loading the versions of plan '${planId}'`);
2191
2040
  }
2192
2041
  const versions = await res.json().catch(() => null);
2193
2042
  if (!versions || versions.length === 0) return null;
@@ -2204,7 +2053,7 @@ function useLivePlanVersions(options) {
2204
2053
  return [plan.planKey, live];
2205
2054
  } catch (err) {
2206
2055
  console.warn(
2207
- `useLivePlanVersions: Plan '${plan.planKey}' Versions-Load failed`,
2056
+ `useLivePlanVersions: loading the versions of plan '${plan.planKey}' failed`,
2208
2057
  err
2209
2058
  );
2210
2059
  return [plan.planKey, null];
@@ -2240,12 +2089,12 @@ function findLatestLive(versions) {
2240
2089
  }
2241
2090
 
2242
2091
  // src/vue/use-manifest.ts
2243
- import { ref as ref23 } from "vue";
2092
+ import { ref as ref22 } from "vue";
2244
2093
  function useManifest(options) {
2245
2094
  const loader = new ManifestLoader(options);
2246
- const manifest = ref23(null);
2247
- const loading = ref23(false);
2248
- const error = ref23(null);
2095
+ const manifest = ref22(null);
2096
+ const loading = ref22(false);
2097
+ const error = ref22(null);
2249
2098
  async function load() {
2250
2099
  loading.value = true;
2251
2100
  error.value = null;
@@ -2273,11 +2122,15 @@ function useManifest(options) {
2273
2122
  // src/vue/use-nav.ts
2274
2123
  import { computed as computed5 } from "vue";
2275
2124
  function useNav(manifest, options = {}) {
2125
+ const { locale } = useSuperAdminI18n();
2126
+ const activeLocale = computed5(() => options.locale ?? locale.value);
2276
2127
  const routes = computed5(() => {
2277
2128
  if (!manifest.value) return [];
2278
- return buildRoutes(manifest.value, options);
2129
+ return buildRoutes(manifest.value, { ...options, locale: activeLocale.value });
2279
2130
  });
2280
- const sidebar = computed5(() => buildSidebar(routes.value));
2131
+ const sidebar = computed5(
2132
+ () => buildSidebar(routes.value, defaultSectionOrder(activeLocale.value))
2133
+ );
2281
2134
  return { routes, sidebar };
2282
2135
  }
2283
2136
 
@@ -2295,6 +2148,7 @@ function useActions(manifest, actions) {
2295
2148
  import { computed as computed7 } from "vue";
2296
2149
  function useTenantActionFlow(manifest, providers = {}) {
2297
2150
  const handlers = useSuperAdminActions();
2151
+ const msg = useSaMessages("tenants");
2298
2152
  const registry = computed7(() => {
2299
2153
  if (!manifest.value) return null;
2300
2154
  return new ActionRegistry(manifest.value, handlers);
@@ -2316,7 +2170,7 @@ function useTenantActionFlow(manifest, providers = {}) {
2316
2170
  if (!reg) return [];
2317
2171
  return availableActions.value.filter((def) => !providers.visibleForRow || providers.visibleForRow(def, row)).map((def) => ({
2318
2172
  def,
2319
- invoke: (r) => runFlow(def, r ?? row, reg, providers)
2173
+ invoke: (r) => runFlow(def, r ?? row, reg, providers, msg.value.actions.successNotify)
2320
2174
  }));
2321
2175
  }
2322
2176
  return { registry, availableActions, actionsForRow, orphanedDefs };
@@ -2330,13 +2184,13 @@ function passesStaticGates(def, capabilities, orphanedKeys) {
2330
2184
  }
2331
2185
  return true;
2332
2186
  }
2333
- async function runFlow(def, row, registry, providers) {
2187
+ async function runFlow(def, row, registry, providers, successTemplate) {
2334
2188
  let reason = null;
2335
2189
  let extras = {};
2336
2190
  if (def.confirmType && def.confirmType !== "none") {
2337
2191
  if (!providers.confirm) {
2338
2192
  throw new Error(
2339
- `useTenantActionFlow: Action "${def.id}" verlangt confirmType="${def.confirmType}", aber kein \`confirm\`-Provider \xFCbergeben.`
2193
+ `useTenantActionFlow: action "${def.id}" requires confirmType="${def.confirmType}", but no \`confirm\` provider was supplied.`
2340
2194
  );
2341
2195
  }
2342
2196
  const c = await providers.confirm(def, { row });
@@ -2348,7 +2202,7 @@ async function runFlow(def, row, registry, providers) {
2348
2202
  if (def.requiresMfa) {
2349
2203
  if (!providers.mfa) {
2350
2204
  throw new Error(
2351
- `useTenantActionFlow: Action "${def.id}" verlangt MFA, aber kein \`mfa\`-Provider \xFCbergeben.`
2205
+ `useTenantActionFlow: action "${def.id}" requires MFA, but no \`mfa\` provider was supplied.`
2352
2206
  );
2353
2207
  }
2354
2208
  mfaCode = await providers.mfa(def, { row });
@@ -2364,7 +2218,7 @@ async function runFlow(def, row, registry, providers) {
2364
2218
  try {
2365
2219
  const input = { row, mfaCode, reason, extras };
2366
2220
  const result = await resolved.handler(input);
2367
- providers.notify?.("positive", `${def.label}: erfolgreich.`);
2221
+ providers.notify?.("positive", formatMessage(successTemplate, { action: def.label }));
2368
2222
  providers.onSuccess?.(def, { row });
2369
2223
  return result;
2370
2224
  } catch (err) {
@@ -2375,13 +2229,12 @@ async function runFlow(def, row, registry, providers) {
2375
2229
  }
2376
2230
 
2377
2231
  // src/vue/use-platform-tenant-actions.ts
2378
- import { computed as computed8, ref as ref24 } from "vue";
2232
+ import { computed as computed8, ref as ref23 } from "vue";
2379
2233
  var DEFAULT_VISIBLE_FOR_ROW = (def, row) => {
2380
2234
  if (def.actionKey === "tenants.suspend") return row.isActive;
2381
2235
  if (def.actionKey === "tenants.reactivate") return !row.isActive;
2382
2236
  return true;
2383
2237
  };
2384
- var DEFAULT_MFA_DESCRIPTION = (def, row) => `${def.label} \u2014 Tenant \u201E${row.name}". TOTP-Code aus Authenticator eingeben.`;
2385
2238
  var DEFAULT_ICON_FOR_ACTION_KEY = (actionKey) => {
2386
2239
  if (actionKey.endsWith(".suspend")) return "block";
2387
2240
  if (actionKey.endsWith(".reactivate")) return "play_arrow";
@@ -2403,11 +2256,16 @@ function defaultToneForActionKey(actionKey) {
2403
2256
  return DEFAULT_TONE_FOR_ACTION_KEY(actionKey);
2404
2257
  }
2405
2258
  function usePlatformTenantActions(options) {
2406
- const mfaDescription = options.mfaDescription ?? DEFAULT_MFA_DESCRIPTION;
2259
+ const msg = useSaMessages("tenants");
2260
+ const defaultMfaDescription = (def, row) => formatMessage(msg.value.actions.mfaDescription, {
2261
+ action: def.label,
2262
+ tenant: row.name
2263
+ });
2264
+ const mfaDescription = options.mfaDescription ?? defaultMfaDescription;
2407
2265
  const iconForActionKey = options.iconForActionKey ?? DEFAULT_ICON_FOR_ACTION_KEY;
2408
2266
  const toneForActionKey = options.toneForActionKey ?? DEFAULT_TONE_FOR_ACTION_KEY;
2409
2267
  const visibleForRow = options.visibleForRow ?? DEFAULT_VISIBLE_FOR_ROW;
2410
- const mfa = ref24({ show: false, description: "", error: "" });
2268
+ const mfa = ref23({ show: false, description: "", error: "" });
2411
2269
  let pendingMfaResolve = null;
2412
2270
  function showMfaDialog(def, ctx) {
2413
2271
  return new Promise((resolve) => {
@@ -2432,7 +2290,7 @@ function usePlatformTenantActions(options) {
2432
2290
  pendingMfaResolve(null);
2433
2291
  }
2434
2292
  }
2435
- const confirmDialog = ref24({
2293
+ const confirmDialog = ref23({
2436
2294
  show: false,
2437
2295
  def: null,
2438
2296
  row: null
@@ -2513,12 +2371,12 @@ function usePlatformTenantActions(options) {
2513
2371
  }
2514
2372
 
2515
2373
  // src/vue/use-batch-columns.ts
2516
- import { ref as ref25, watch as watch4 } from "vue";
2374
+ import { ref as ref24, watch as watch4 } from "vue";
2517
2375
  function useBatchColumns(manifest, tenantIds, options = {}) {
2518
2376
  const fetcher = new BatchColumnFetcher(options);
2519
- const data = ref25({});
2520
- const loading = ref25(false);
2521
- const error = ref25(null);
2377
+ const data = ref24({});
2378
+ const loading = ref24(false);
2379
+ const error = ref24(null);
2522
2380
  async function load() {
2523
2381
  if (!manifest.value || tenantIds.value.length === 0) {
2524
2382
  data.value = {};
@@ -2567,13 +2425,13 @@ function createPlatformLoaders(options) {
2567
2425
 
2568
2426
  // src/vue/manifest-store-factory.ts
2569
2427
  import { defineStore } from "pinia";
2570
- import { ref as ref26 } from "vue";
2428
+ import { ref as ref25 } from "vue";
2571
2429
  function createManifestStore(options) {
2572
2430
  return defineStore(options.id ?? "admin-manifest", () => {
2573
- const manifest = ref26(null);
2574
- const loading = ref26(false);
2575
- const error = ref26(null);
2576
- const loaded = ref26(false);
2431
+ const manifest = ref25(null);
2432
+ const loading = ref25(false);
2433
+ const error = ref25(null);
2434
+ const loaded = ref25(false);
2577
2435
  let inflight = null;
2578
2436
  async function load() {
2579
2437
  loading.value = true;
@@ -2612,16 +2470,6 @@ function createManifestStore(options) {
2612
2470
  });
2613
2471
  }
2614
2472
 
2615
- // src/components/dialogs/types.ts
2616
- var DEFAULT_PILOT_COPY = {
2617
- tenantSubtitle: "Stammdaten des Mandanten",
2618
- tenantNameLabel: "Name des Mandanten",
2619
- tenantNamePlaceholder: "z. B. Muster GmbH",
2620
- slugPlaceholder: "muster-mandant",
2621
- adminEmailPlaceholder: "admin@example.com",
2622
- notePlaceholder: "z. B. Sales-Pilot \xB7 Demo-Zugang"
2623
- };
2624
-
2625
2473
  // src/components/bundle-editor/catalog-i18n.ts
2626
2474
  var CATALOG_DEFAULT_LOCALE = "de";
2627
2475
  function localized(i18n, locale, field) {
@@ -2782,8 +2630,185 @@ var DEFAULT_I18N_DE = {
2782
2630
  packageSnapshotPriceTotal: "Gesamtpreis",
2783
2631
  packageSnapshotNone: "Diese Subscription wurde nicht \xFCber ein Webseiten-Angebot abgeschlossen.",
2784
2632
  packageSnapshotShowRaw: "Rohdaten anzeigen",
2785
- packageSnapshotHideRaw: "Rohdaten ausblenden"
2633
+ packageSnapshotHideRaw: "Rohdaten ausblenden",
2634
+ errorLabel: "Fehler",
2635
+ myBundlesTitle: "Meine Bundles",
2636
+ myBundlesSubtitle: "Eigenst\xE4ndig gebuchte Add-On-Pakete zu deinem Plan. Mindestlaufzeit + K\xFCndigungs- Termin pro Bundle.",
2637
+ myBundlesEmptyPrefix: "Du hast noch kein Bundle gebucht. \xDCber",
2638
+ myBundlesEmptySuffix: "kannst du dein Paket um zus\xE4tzliche Features & Quotas erweitern.",
2639
+ myBundlesBookedSince: "Gebucht seit",
2640
+ myBundlesCanceledAt: "Gek\xFCndigt am",
2641
+ myBundlesRunsUntil: "l\xE4uft bis",
2642
+ myBundlesCancelInProgress: "K\xFCndige \u2026",
2643
+ myBundlesBookInProgress: "Buche \u2026",
2644
+ myBundlesCancelConfirm: "Bundle wirklich k\xFCndigen? Die K\xFCndigung wird zum n\xE4chstm\xF6glichen Termin wirksam.",
2645
+ myBundlesStatusCanceledPending: "K\xFCndigung wirksam ab \u2026",
2646
+ myBundlesStatusEnded: "Beendet",
2647
+ myBundlesAddBundleLabel: "Bundle",
2648
+ myBundlesAddSelectPlaceholder: "\u2014 bitte w\xE4hlen \u2014",
2649
+ myBundlesPricePerMonthShort: "\u20AC / Mo",
2650
+ myBundlesHiddenIncompatible: "weitere Bundle(s) ausgeblendet \u2014 nicht kompatibel mit Plan",
2651
+ myBundlesBundleVersionIdLabel: "BundleVersion-ID",
2652
+ myBundlesBundleVersionIdPlaceholder: "UUID der gew\xFCnschten Bundle-Version",
2653
+ myBundlesMinimumTermLabel: "Mindestlaufzeit (Monate, optional)",
2654
+ myBundlesMinimumTermPlaceholder: "Default: 12"
2655
+ };
2656
+ var DEFAULT_I18N_EN = {
2657
+ sectionTitle: "Plan & usage",
2658
+ sectionSubtitle: "Current plan, usage and bundles.",
2659
+ loading: "Loading \u2026",
2660
+ noSubscription: "No subscription found for this tenant.",
2661
+ activePlan: "Current plan",
2662
+ cycleMonthly: "Monthly",
2663
+ cycleYearly: "Yearly",
2664
+ statusActive: "Active",
2665
+ statusTrial: "Trial",
2666
+ statusPastDue: "Payment overdue",
2667
+ statusCanceled: "Canceled",
2668
+ statusPendingSales: "Sales review",
2669
+ trialEndsAt: "Trial ends on",
2670
+ pilotEndsAt: "Pilot ends on",
2671
+ nextBillingDate: "Next billing date",
2672
+ pendingChange: "Pending plan change",
2673
+ changeFromTo: "Change to",
2674
+ changeEffectiveAt: "effective as of",
2675
+ changePlanButton: "Change plan",
2676
+ cancelSubscriptionButton: "Cancel subscription",
2677
+ usageTitle: "Usage",
2678
+ featuresOverviewTitle: "Features",
2679
+ featuresActive: "Included",
2680
+ featuresLocked: "Not included",
2681
+ bundlesStoreTitle: "Bundles",
2682
+ bundlesBookedTitle: "Booked bundles",
2683
+ bundlesAvailableTitle: "Available bundles",
2684
+ bundlesAvailableEmpty: "There are currently no additional bundles available.",
2685
+ bundlesPerMonth: "net/month",
2686
+ bundleBookAction: "Book bundle",
2687
+ bundleBookInProgress: "Booking \u2026",
2688
+ bundleCancelAction: "Cancel",
2689
+ bundleReactivateAction: "Reactivate",
2690
+ bundleReactivateConfirmTitle: "Reactivate bundle",
2691
+ bundleReactivateConfirmBody: "The cancellation will be reverted. The bundle stays booked, continues to run normally and will be billed again.",
2692
+ bundleCanceledAt: "Canceled effective",
2693
+ bundleMinimumTermUntil: "Minimum term until",
2694
+ bundleIncludesLabel: "Includes",
2695
+ bundleAlreadyBooked: "Already booked",
2696
+ bundleIncompatible: "Not compatible with the current plan",
2697
+ bundleMissingRequires: "Requires",
2698
+ bundlePreviewAddTitle: "Book bundle",
2699
+ bundlePreviewCancelTitle: "Cancel bundle",
2700
+ bundlePreviewLoading: "Calculating preview \u2026",
2701
+ bundlePreviewProrationTitle: "Prorated billing",
2702
+ bundlePreviewProratedNow: "Prorated amount due today",
2703
+ bundlePreviewProrationDays: "days",
2704
+ bundlePreviewNextPeriod: "Regular price from the next period",
2705
+ bundlePreviewTrialNote: "Nothing is charged during the trial \u2014 billing starts with the first paid period.",
2706
+ bundlePreviewNoPrice: "No list price is configured for the current billing cycle.",
2707
+ bundlePreviewMinimumTermLabel: "Minimum term",
2708
+ bundlePreviewMinimumTermMonths: "months, until",
2709
+ bundlePreviewMinimumTermNone: "No minimum term",
2710
+ bundlePreviewRedundantTitle: "Features already included (would be paid for twice)",
2711
+ bundlePreviewRedundantCoveredByPlan: "already in the plan",
2712
+ bundlePreviewRedundantCoveredByBundle: "already in bundle",
2713
+ bundlePreviewMissingRequiresTitle: "Missing prerequisites",
2714
+ bundlePreviewBlockersTitle: "Booking not possible",
2715
+ bundlePreviewWarningsTitle: "Notes",
2716
+ bundlePreviewEffectiveAt: "Cancellation effective as of",
2717
+ bundlePreviewSavings: "Savings per period once effective",
2718
+ bundlePreviewConfirmAdd: "Book (chargeable)",
2719
+ bundlePreviewConfirmCancel: "Confirm cancellation",
2720
+ bundlePreviewInProgress: "Processing \u2026",
2721
+ bundlePreviewClose: "Cancel",
2722
+ pendingVersionTitle: "Upcoming plan change",
2723
+ pendingVersionChipNonRegressive: "Improvement",
2724
+ pendingVersionChipRegressive: "Confirmation required",
2725
+ pendingVersionEffectiveAt: "Effective as of",
2726
+ pendingVersionAcceptAction: "Accept changes",
2727
+ pendingVersionAcceptInProgress: "Accepting \u2026",
2728
+ pendingVersionAcceptedAt: "Accepted on",
2729
+ wizardTitle: "Change plan",
2730
+ wizardClose: "Close",
2731
+ wizardCurrent: "Current",
2732
+ wizardBadgeCurrent: "active",
2733
+ wizardBadgePopular: "popular",
2734
+ wizardPriceUnitMonthly: "net/month",
2735
+ wizardPriceUnitYearly: "net/year",
2736
+ wizardPriceOnRequest: "on request",
2737
+ wizardStepChoose: "Choose plan",
2738
+ wizardStepChooseIntro: "Choose your target plan and the billing cycle. In the next step we show the usage check and the feature diff.",
2739
+ wizardStepPreview: "Preview",
2740
+ wizardStepConfirm: "Confirm",
2741
+ wizardNext: "Next",
2742
+ wizardBack: "Back",
2743
+ wizardPreviewLoading: "Calculating preview \u2026",
2744
+ wizardEffectiveAtLabel: "Effective as of",
2745
+ wizardEffectiveImmediate: "Effective immediately",
2746
+ wizardProrationTitle: "Prorated billing",
2747
+ wizardProrationLine: "Additional amount until the end of the period:",
2748
+ wizardProrationDays: "days",
2749
+ wizardLimitsTitle: "Limit comparison",
2750
+ wizardLimitsUsed: "Usage",
2751
+ wizardLimitsCurrent: "Current",
2752
+ wizardLimitsTarget: "Target",
2753
+ wizardFeaturesGained: "Newly unlocked",
2754
+ wizardFeaturesLost: "Features you lose",
2755
+ wizardBlockersTitle: "Blockers",
2756
+ wizardConfirmImmediate: "The change takes effect immediately.",
2757
+ wizardConfirmScheduled: "The change takes effect on",
2758
+ wizardConfirmAction: "Confirm change",
2759
+ wizardConfirmInProgress: "Changing \u2026",
2760
+ wizardConfirmPriceTitle: "Price overview",
2761
+ wizardConfirmProratedNow: "Prorated amount due today",
2762
+ wizardConfirmRecurringNext: "Regular price from the next period",
2763
+ wizardConfirmRecurringFrom: "Regular price due from",
2764
+ wizardConfirmPerCycleMonthly: "per month",
2765
+ wizardConfirmPerCycleYearly: "per year",
2766
+ wizardConfirmTrialNote: "Nothing is charged during the trial.",
2767
+ wizardConfirmRecurringTrialEnd: "Regular price from the end of the trial",
2768
+ wizardChangeTypeUpgrade: "Upgrade",
2769
+ wizardChangeTypeDowngrade: "Downgrade",
2770
+ wizardChangeTypeCycle: "Cycle change",
2771
+ wizardChangeTypeNoop: "No change",
2772
+ packageSnapshotTitle: "Booked plan (snapshot)",
2773
+ packageSnapshotSubtitle: "Read-only copy of the plan as it was marketed at the time of purchase.",
2774
+ packageSnapshotCapturedAt: "Captured on",
2775
+ packageSnapshotOfferRef: "Offer reference",
2776
+ packageSnapshotPlanLabel: "Plan",
2777
+ packageSnapshotPlanVersionLabel: "Plan version",
2778
+ packageSnapshotCycleLabel: "Billing cycle",
2779
+ packageSnapshotBundlesLabel: "Included bundles",
2780
+ packageSnapshotBundlesEmpty: "No bundles in the plan.",
2781
+ packageSnapshotPriceMonthly: "Monthly price",
2782
+ packageSnapshotPriceYearly: "Yearly price",
2783
+ packageSnapshotPriceTotal: "Total price",
2784
+ packageSnapshotNone: "This subscription was not created through a website offer.",
2785
+ packageSnapshotShowRaw: "Show raw data",
2786
+ packageSnapshotHideRaw: "Hide raw data",
2787
+ errorLabel: "Error",
2788
+ myBundlesTitle: "My bundles",
2789
+ myBundlesSubtitle: "Add-on packages booked independently on top of your plan. Minimum term + cancellation date per bundle.",
2790
+ myBundlesEmptyPrefix: "You have not booked a bundle yet. Use",
2791
+ myBundlesEmptySuffix: "to extend your plan with additional features & quotas.",
2792
+ myBundlesBookedSince: "Booked since",
2793
+ myBundlesCanceledAt: "Canceled on",
2794
+ myBundlesRunsUntil: "runs until",
2795
+ myBundlesCancelInProgress: "Canceling \u2026",
2796
+ myBundlesBookInProgress: "Booking \u2026",
2797
+ myBundlesCancelConfirm: "Really cancel this bundle? The cancellation takes effect on the next possible date.",
2798
+ myBundlesStatusCanceledPending: "Cancellation effective as of \u2026",
2799
+ myBundlesStatusEnded: "Ended",
2800
+ myBundlesAddBundleLabel: "Bundle",
2801
+ myBundlesAddSelectPlaceholder: "\u2014 please select \u2014",
2802
+ myBundlesPricePerMonthShort: "\u20AC / mo",
2803
+ myBundlesHiddenIncompatible: "more bundle(s) hidden \u2014 not compatible with plan",
2804
+ myBundlesBundleVersionIdLabel: "BundleVersion ID",
2805
+ myBundlesBundleVersionIdPlaceholder: "UUID of the desired bundle version",
2806
+ myBundlesMinimumTermLabel: "Minimum term (months, optional)",
2807
+ myBundlesMinimumTermPlaceholder: "Default: 12"
2786
2808
  };
2809
+ function defaultTenantPlanSectionI18n(locale) {
2810
+ return locale === "en" ? DEFAULT_I18N_EN : DEFAULT_I18N_DE;
2811
+ }
2787
2812
  export {
2788
2813
  ADMIN_UI_VERSION,
2789
2814
  ActionDefNotInManifestError,
@@ -2793,12 +2818,11 @@ export {
2793
2818
  BootLoadError,
2794
2819
  BootLoader,
2795
2820
  BundlesApiError,
2796
- BusinessTypesApiError,
2797
2821
  CATALOG_DEFAULT_LOCALE,
2798
2822
  CatalogEntriesApiError,
2799
2823
  DEFAULT_I18N_DE,
2800
- DEFAULT_PILOT_COPY,
2801
- DEFAULT_SECTION_ORDER,
2824
+ DEFAULT_I18N_EN,
2825
+ DEFAULT_SA_LOCALE,
2802
2826
  DEFAULT_STANDARD_PAGE_ROUTES,
2803
2827
  DEFAULT_YEARLY_FACTOR,
2804
2828
  DiscoveryLoadError,
@@ -2812,11 +2836,15 @@ export {
2812
2836
  PlansApiError,
2813
2837
  ProjectPageHost,
2814
2838
  PromotionsApiError,
2839
+ SA_INTL_LOCALES,
2840
+ SA_LOCALES,
2841
+ SA_MESSAGES,
2815
2842
  SUPER_ADMIN_ACTIONS_KEY,
2816
2843
  SUPER_ADMIN_BRAND_KEY,
2817
2844
  SUPER_ADMIN_ENDPOINTS_KEY,
2818
2845
  SUPER_ADMIN_EXTENSIONS_KEY,
2819
2846
  SUPER_ADMIN_HTTP_KEY,
2847
+ SUPER_ADMIN_I18N_KEY,
2820
2848
  SUPER_ADMIN_LOGIN_ADAPTER_KEY,
2821
2849
  SUPER_ADMIN_MANIFEST_KEY,
2822
2850
  SUPER_ADMIN_NOTIFY_KEY,
@@ -2832,15 +2860,23 @@ export {
2832
2860
  createManifestStore,
2833
2861
  createPlatformLoaders,
2834
2862
  createProjectPageHostRoute,
2863
+ createSuperAdminI18n,
2835
2864
  defaultHttpClient,
2836
2865
  defaultIconForActionKey,
2837
2866
  defaultKvStore,
2867
+ defaultSectionOrder,
2868
+ defaultTenantPlanSectionI18n,
2838
2869
  defaultToneForActionKey,
2870
+ defineMessages,
2871
+ formatCurrency,
2872
+ formatMessage,
2839
2873
  getJson,
2840
2874
  listOpenDrafts,
2875
+ mergeMessages,
2841
2876
  postJson,
2842
2877
  provideEntitlement,
2843
2878
  resolveExtension,
2879
+ resolveMessages,
2844
2880
  trimTrailingSlashes,
2845
2881
  useActions,
2846
2882
  useApiList,
@@ -2850,8 +2886,6 @@ export {
2850
2886
  useBundleVersions,
2851
2887
  useBundleVersionsMap,
2852
2888
  useBundles,
2853
- useBusinessTypeVersions,
2854
- useBusinessTypes,
2855
2889
  useCatalogEntries,
2856
2890
  useDiscovery,
2857
2891
  useEntitlement,
@@ -2867,12 +2901,14 @@ export {
2867
2901
  usePlatformTenantActions,
2868
2902
  usePromotions,
2869
2903
  usePublicBoot,
2904
+ useSaMessages,
2870
2905
  useSubscriptionDraft,
2871
2906
  useSuperAdminActions,
2872
2907
  useSuperAdminBrand,
2873
2908
  useSuperAdminEndpoints,
2874
2909
  useSuperAdminExtensions,
2875
2910
  useSuperAdminHttp,
2911
+ useSuperAdminI18n,
2876
2912
  useSuperAdminLoginAdapter,
2877
2913
  useSuperAdminManifest,
2878
2914
  useTenantActionFlow,