@vtex/faststore-plugin-buyer-portal 2.0.13 → 2.0.14

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 (219) hide show
  1. package/CHANGELOG.md +18 -1
  2. package/cms/b2b/components/.gitkeep +0 -0
  3. package/cms/b2b/pages/cms_content_type__i18n.jsonc +36 -0
  4. package/cypress/integration/localization.test.ts +482 -0
  5. package/cypress/support/commands.ts +8 -0
  6. package/docs/i18n/i18n-messages-format.md +391 -0
  7. package/docs/i18n/locales.json +701 -0
  8. package/docs/i18n/migration-inventory.md +959 -0
  9. package/package.json +3 -3
  10. package/specs/custom-localization-system.md +711 -0
  11. package/specs/multi-locale-e2e-validation.md +277 -0
  12. package/src/__mocks__/discovery.config.ts +12 -0
  13. package/src/features/accounting-fields/components/AccountingConfirmDelete/AccountingConfirmDelete.tsx +14 -4
  14. package/src/features/accounting-fields/components/AccountingFieldConfirmEdit/AccountingFieldConfirmEdit.tsx +11 -6
  15. package/src/features/accounting-fields/components/AccountingFieldDropdown/AccountingFieldDropdown.tsx +5 -3
  16. package/src/features/accounting-fields/components/AccountingFieldForm/AccountingFieldForm.tsx +33 -23
  17. package/src/features/accounting-fields/components/AccountingValueConfirmEdit/AccountingValueConfirmEdit.tsx +10 -6
  18. package/src/features/accounting-fields/components/AccountingValueDropdown/AccountingValueDropdown.tsx +19 -9
  19. package/src/features/accounting-fields/components/AccountingValueForm/AccountingValueForm.tsx +21 -10
  20. package/src/features/accounting-fields/components/CreateAccountingFieldDrawer/CreateAccountingFieldDrawer.tsx +11 -8
  21. package/src/features/accounting-fields/components/CreateAccountingValueDrawer/CreateAccountingValueDrawer.tsx +18 -7
  22. package/src/features/accounting-fields/components/DeleteAccountingFieldDrawer/DeleteAccountingFieldDrawer.tsx +14 -12
  23. package/src/features/accounting-fields/components/DeleteAccountingValueDrawer/DeleteAccountingValueDrawer.tsx +20 -10
  24. package/src/features/accounting-fields/components/EditAccountingFieldDrawer/EditAccountingFieldDrawer.tsx +5 -3
  25. package/src/features/accounting-fields/components/EditAccountingValueDrawer/EditAccountingValueDrawer.tsx +13 -6
  26. package/src/features/accounting-fields/components/RemoveValueFromUnitDrawer/RemoveValueFromUnitDrawer.tsx +19 -8
  27. package/src/features/accounting-fields/layouts/AccountingFieldLayout/AccountingFieldLayout.tsx +11 -9
  28. package/src/features/addresses/components/AddRecipientsDrawer/AddRecipientsDrawer.tsx +13 -7
  29. package/src/features/addresses/components/AddressDropdownMenu/AddressDropdownMenu.tsx +22 -20
  30. package/src/features/addresses/components/AddressForm/AddressForm.tsx +33 -22
  31. package/src/features/addresses/components/AddressLine/AddressLine.tsx +29 -25
  32. package/src/features/addresses/components/AddressLocationsList/AddressLocationsList.tsx +15 -6
  33. package/src/features/addresses/components/AddressRecipientsList/AddressRecipientsList.tsx +9 -4
  34. package/src/features/addresses/components/AddressesCard/AddressesCard.tsx +8 -5
  35. package/src/features/addresses/components/CreateAddressDrawer/CreateAddressDrawer.tsx +27 -14
  36. package/src/features/addresses/components/CreateAddressSettingsDrawer/CreateAddressSettingsDrawer.tsx +26 -21
  37. package/src/features/addresses/components/DeleteAddressDrawer/DeleteAddressDrawer.tsx +20 -16
  38. package/src/features/addresses/components/DeleteAddressLocationDrawer/DeleteAddressLocationDrawer.tsx +26 -14
  39. package/src/features/addresses/components/DeleteRecipientAddressDrawer/DeleteRecipientAddressDrawer.tsx +20 -17
  40. package/src/features/addresses/components/EditAddressDrawer/EditAddressDrawer.tsx +12 -6
  41. package/src/features/addresses/components/EditAddressLocationDrawer/EditAddressLocationDrawer.tsx +24 -17
  42. package/src/features/addresses/components/EditRecipientAddressDrawer/EditRecipientAddressDrawer.tsx +17 -15
  43. package/src/features/addresses/components/LocationForm/LocationField/LocationField.tsx +8 -5
  44. package/src/features/addresses/components/LocationForm/LocationForm.tsx +9 -3
  45. package/src/features/addresses/components/LocationsDrawer/LocationsDrawer.tsx +15 -9
  46. package/src/features/addresses/components/RecipientsForm/RecipientItem/RecipientItem.tsx +55 -46
  47. package/src/features/addresses/components/RecipientsForm/RecipientsForm.tsx +4 -1
  48. package/src/features/addresses/components/RemoveAddressDrawer/RemoveAddressDrawer.tsx +21 -14
  49. package/src/features/addresses/layouts/AddressDetailsLayout/AddressDetailsLayout.tsx +16 -9
  50. package/src/features/addresses/layouts/AddressesLayout/AddressesLayout.tsx +11 -8
  51. package/src/features/b2b-agent/layouts/B2BAgentLayout/B2BAgentLayout.tsx +3 -1
  52. package/src/features/budgets/components/BudgetAddForm/BudgetAddForm.tsx +14 -12
  53. package/src/features/budgets/components/BudgetAddSuccess/BudgetAddSuccess.tsx +16 -14
  54. package/src/features/budgets/components/BudgetAllocationsSelection/BudgetAllocationsSelection.tsx +8 -5
  55. package/src/features/budgets/components/BudgetAllocationsTable/BudgetAllocationsTable.tsx +9 -6
  56. package/src/features/budgets/components/BudgetDeleteDrawer/BudgetDeleteDrawer.tsx +23 -17
  57. package/src/features/budgets/components/BudgetEditNotificationDrawer/BudgetEditNotificationDrawer.tsx +13 -6
  58. package/src/features/budgets/components/BudgetNotificationForm/BudgetNotificationForm.tsx +31 -24
  59. package/src/features/budgets/components/BudgetNotificationsInfo/BudgetNotificationsInfo.tsx +15 -9
  60. package/src/features/budgets/components/BudgetRemainingBalance/BudgetRemainingBalance.tsx +6 -2
  61. package/src/features/budgets/components/BudgetSettingsInfo/BudgetSettingsInfo.tsx +27 -10
  62. package/src/features/budgets/components/BudgetUsersTable/BudgetUsersTable.tsx +14 -7
  63. package/src/features/budgets/components/BudgetsTable/BudgetsTable.tsx +11 -8
  64. package/src/features/budgets/components/CreateBudgetAllocationDrawer/CreateBudgetAllocationDrawer.tsx +8 -5
  65. package/src/features/budgets/components/CreateBudgetDrawer/CreateBudgetDrawer.tsx +31 -18
  66. package/src/features/budgets/components/DeleteBudgetAllocationDrawer/DeleteBudgetAllocationDrawer.tsx +17 -12
  67. package/src/features/budgets/components/EditBudgetDrawer/EditBudgetDrawer.tsx +14 -8
  68. package/src/features/budgets/components/EmptyState.tsx/EmptyState.tsx +4 -1
  69. package/src/features/budgets/layouts/BudgetsDetailsLayout/BudgetsDetailsLayout.tsx +7 -5
  70. package/src/features/budgets/layouts/BudgetsLayout/BudgetsLayout.tsx +5 -3
  71. package/src/features/budgets/messages/budgetNotifications.ts +5 -5
  72. package/src/features/budgets/utils/handleBudgetError.tsx +5 -8
  73. package/src/features/budgets/utils/handleBudgetError.types.ts +3 -0
  74. package/src/features/buying-policies/components/AccountingFieldCriteriaSelector/AccountingFieldCriteriaSelector.tsx +5 -3
  75. package/src/features/buying-policies/components/AccountingFieldCriteriaSelector/AccountingValueCriteriaSelector.tsx +20 -9
  76. package/src/features/buying-policies/components/AddBuyingPolicyDrawer/AddBuyingPolicyDrawer.tsx +8 -5
  77. package/src/features/buying-policies/components/BasicBuyingPolicyDrawer/BasicBuyingPolicyDrawer.tsx +49 -33
  78. package/src/features/buying-policies/components/BudgetCriteriaSelector/BudgetCriteriaSelector.tsx +8 -2
  79. package/src/features/buying-policies/components/BuyingPolicyDropdownMenu/BuyingPolicyDropdownMenu.tsx +5 -3
  80. package/src/features/buying-policies/components/DeleteBuyingPolicyDrawer/DeleteBuyingPolicyDrawer.tsx +28 -24
  81. package/src/features/buying-policies/components/UpdateBuyingPolicyDrawer/UpdateBuyingPolicyDrawer.tsx +10 -7
  82. package/src/features/buying-policies/layouts/BuyingPoliciesLayout/BuyingPoliciesLayout.tsx +11 -4
  83. package/src/features/buying-policies/layouts/BuyingPolicyDetailsLayout/BuyingPolicyDetailsLayout.tsx +26 -9
  84. package/src/features/buying-policies/utils/accountingFieldCriteriaHelpers.ts +2 -2
  85. package/src/features/buying-policies/utils/buyingPoliciesWorkflowTypes.ts +3 -3
  86. package/src/features/buying-policies/utils/orderFieldsCriteriaOptions.ts +8 -8
  87. package/src/features/buying-policies/utils/spendingLimitsCriteriaOptions.ts +6 -6
  88. package/src/features/contracts/components/ContractsCard/ContractsCard.tsx +7 -5
  89. package/src/features/contracts/layouts/ContractsLayout/ContractsLayout.tsx +9 -4
  90. package/src/features/credit-cards/components/CreateCreditCardDrawer/CreateCreditCardDrawer.tsx +17 -11
  91. package/src/features/credit-cards/components/CreditCardDropdownMenu/CreditCardDropdownMenu.tsx +17 -11
  92. package/src/features/credit-cards/components/CreditCardForm/CreditCardForm.tsx +8 -5
  93. package/src/features/credit-cards/components/CreditCardSettingsDrawer/CreditCardSettingsDrawer.tsx +10 -8
  94. package/src/features/credit-cards/components/DeleteCreditCardDrawer/DeleteCreditCardDrawer.tsx +19 -14
  95. package/src/features/credit-cards/components/EditCreditCardDrawer/EditCreditCardDrawer.tsx +14 -13
  96. package/src/features/credit-cards/components/RemoveCreditCardDrawer/RemoveCreditCardDrawer.tsx +18 -15
  97. package/src/features/credit-cards/layouts/CreditCardsLayout/CreditCardLayout.tsx +10 -4
  98. package/src/features/order-entry/layouts/OrderEntryLayout.tsx +3 -1
  99. package/src/features/org-units/components/AddAllToOrgUnitDropdown/AddAllToOrgUnitDropdown.tsx +11 -9
  100. package/src/features/org-units/components/AuthSetupDrawer/AuthSetupDrawer.tsx +28 -16
  101. package/src/features/org-units/components/CreateOrgUnitDrawer/CreateOrgUnitDrawer.tsx +18 -12
  102. package/src/features/org-units/components/DeleteOrgUnitDrawer/DeleteOrgUnitDrawer.tsx +28 -29
  103. package/src/features/org-units/components/OrgUnitBreadcrumb/OrgUnitBreadcrumbLink.tsx +4 -4
  104. package/src/features/org-units/components/OrgUnitDetailsDropdownMenu/OrgUnitDetailsDropdownMenu.tsx +4 -2
  105. package/src/features/org-units/components/OrgUnitDetailsNavbar/OrgUnitDetailsNavbar.tsx +23 -5
  106. package/src/features/org-units/components/OrgUnitDetailsNavbar/org-unit-details-navbar.scss +18 -2
  107. package/src/features/org-units/components/OrgUnitsDropdownMenu/OrgUnitsDropdownMenu.tsx +6 -4
  108. package/src/features/org-units/components/OrgUnitsHierarchyTree/OrgUnitsHierarchyTree.tsx +9 -6
  109. package/src/features/org-units/components/OrganizationalUnitsCard/OrganizationalUnitsCard.tsx +15 -7
  110. package/src/features/org-units/components/UpdateOrgUnitDrawer/UpdateOrgUnitDrawer.tsx +15 -9
  111. package/src/features/org-units/layouts/OrgUnitDetailsLayout/OrgUnitDetailsLayout.tsx +27 -26
  112. package/src/features/org-units/layouts/OrgUnitsLayout/OrgUnitsLayout.tsx +8 -3
  113. package/src/features/payment-methods/components/AddPaymentMethodsDrawer/AddPaymentMethodsDrawer.tsx +29 -18
  114. package/src/features/payment-methods/components/PaymentMethodSettingsDrawer/PaymentMethodSettingsDrawer.tsx +13 -9
  115. package/src/features/payment-methods/components/RemoveMethodButton/RemoveMethodButton.tsx +5 -2
  116. package/src/features/payment-methods/components/RemovePaymentMethodsDrawer/RemovePaymentMethodsDrawer.tsx +10 -7
  117. package/src/features/payment-methods/hooks/useRemovePaymentMethodSubmit.ts +6 -4
  118. package/src/features/payment-methods/layouts/PaymentMethodsLayout/PaymentMethodsLayout.tsx +21 -15
  119. package/src/features/product-assortment/components/ProductAssortmentTable/ProductAssortmentTable.tsx +11 -7
  120. package/src/features/product-assortment/layouts/ProductAssortmentLayout/ProductAssortmentLayout.tsx +9 -6
  121. package/src/features/profile/components/ProfileCard/ProfileCard.tsx +8 -5
  122. package/src/features/profile/components/ProfileSummary/ProfileSummary.tsx +13 -6
  123. package/src/features/profile/layouts/ProfileLayout/ProfileLayout.tsx +16 -6
  124. package/src/features/roles/layout/RoleDetailsLayout/RoleDetailsLayout.tsx +4 -2
  125. package/src/features/roles/layout/RolesLayout/RolesLayout.tsx +5 -3
  126. package/src/features/shared/components/BasicCard/BasicCard.tsx +6 -4
  127. package/src/features/shared/components/BasicCard/BasicCardLine.tsx +5 -4
  128. package/src/features/shared/components/CustomerSwitch/CustomerSwitchDrawer.tsx +10 -2
  129. package/src/features/shared/components/CustomerSwitch/CustomerSwitchSearch.tsx +4 -1
  130. package/src/features/shared/components/DropdownFilter/DropdownFilter.tsx +11 -7
  131. package/src/features/shared/components/Error/Error.tsx +13 -6
  132. package/src/features/shared/components/HeaderInside/HeaderInside.tsx +5 -2
  133. package/src/features/shared/components/InternalSearch/InternalSearch.tsx +4 -1
  134. package/src/features/shared/components/InternalTopbar/InternalTopbar.tsx +7 -5
  135. package/src/features/shared/components/MainLinksDropdownMenu/MainLinksDropdownMenu.tsx +23 -8
  136. package/src/features/shared/components/OrgUnitInputSearch/OrgUnitInputSearch.tsx +7 -2
  137. package/src/features/shared/components/Pagination/Pagination.tsx +6 -2
  138. package/src/features/shared/components/Paginator/Counter.tsx +11 -5
  139. package/src/features/shared/components/Paginator/Interval.tsx +4 -3
  140. package/src/features/shared/components/Paginator/NextPageButton.tsx +6 -2
  141. package/src/features/shared/components/SettingsDrawer/SettingsDrawer.tsx +6 -4
  142. package/src/features/shared/components/SettingsDrawer/SettingsDrawerListType.tsx +11 -10
  143. package/src/features/shared/components/SettingsDrawer/listTypeOptions.ts +10 -7
  144. package/src/features/shared/components/SortFilter/SortFilter.tsx +15 -8
  145. package/src/features/shared/components/Table/TableRow/TableRow.tsx +5 -1
  146. package/src/features/shared/components/VerticalNav/VerticalNavLink.tsx +7 -3
  147. package/src/features/shared/layouts/BaseTabsLayout/Navbar.tsx +28 -4
  148. package/src/features/shared/layouts/BaseTabsLayout/about-drawer/AboutDrawer.tsx +15 -5
  149. package/src/features/shared/layouts/BaseTabsLayout/base-tabs-layout.scss +24 -9
  150. package/src/features/shared/layouts/BaseTabsLayout/sidebar-drawer/SidebarDrawer.tsx +5 -2
  151. package/src/features/shared/layouts/ContractTabsLayout/ContractTabsLayout.tsx +10 -5
  152. package/src/features/shared/layouts/ErrorTabsLayout/ErrorTabsLayout.tsx +7 -4
  153. package/src/features/shared/layouts/FinanceTabsLayout/FinanceTabsLayout.tsx +9 -4
  154. package/src/features/shared/layouts/LoadingTabsLayout/LoadingTabsLayout.tsx +7 -4
  155. package/src/features/shared/layouts/OrgUnitTabsLayout/OrgUnitTabLayout.tsx +3 -0
  156. package/src/features/shared/layouts/SumaPageLayout/FullSidebarNav.tsx +13 -7
  157. package/src/features/shared/layouts/SumaPageLayout/SumaSidebar.tsx +9 -5
  158. package/src/features/shared/localization/LocalizationContext.tsx +35 -0
  159. package/src/features/shared/localization/__tests__/createLocalize.test.ts +166 -0
  160. package/src/features/shared/localization/__tests__/get-localization-labels.service.test.ts +202 -0
  161. package/src/features/shared/localization/clients/LocalizationClient.ts +19 -0
  162. package/src/features/shared/localization/constants.ts +31 -0
  163. package/src/features/shared/localization/createLocalize.ts +78 -0
  164. package/src/features/shared/localization/services/get-localization-labels.service.ts +76 -0
  165. package/src/features/shared/localization/types.ts +66 -0
  166. package/src/features/shared/localization/withLocalization.tsx +22 -0
  167. package/src/features/shared/types/AuthRouteProps.ts +5 -0
  168. package/src/features/shared/types/LoaderData.ts +1 -0
  169. package/src/features/shared/utils/addresLabelToPropMapping.ts +10 -10
  170. package/src/features/shared/utils/constants.ts +1 -4
  171. package/src/features/shared/utils/getContractSettingsLinks.ts +17 -12
  172. package/src/features/shared/utils/getFinanceSettingsLinks.ts +14 -9
  173. package/src/features/shared/utils/getKeyByValue.ts +2 -2
  174. package/src/features/shared/utils/getOrganizationSettingsLinks.ts +13 -3
  175. package/src/features/shared/utils/getSumaListingSidebarLinks.ts +15 -10
  176. package/src/features/shared/utils/index.ts +2 -0
  177. package/src/features/shared/utils/routeLayoutMapping.ts +30 -30
  178. package/src/features/shared/utils/search.tsx +10 -0
  179. package/src/features/shared/utils/withAuth.tsx +6 -0
  180. package/src/features/shared/utils/withAuthLoader.ts +11 -0
  181. package/src/features/shared/utils/withLoaderErrorBoundary.ts +9 -0
  182. package/src/features/shared/utils/withProviders.tsx +13 -2
  183. package/src/features/users/components/CreateUserDrawer/CreateUserDrawer.tsx +39 -27
  184. package/src/features/users/components/CreateUserDrawerWithUsername/CreateUserDrawerWithUsername.tsx +41 -39
  185. package/src/features/users/components/DeleteUserDrawer/DeleteUserDrawer.tsx +27 -23
  186. package/src/features/users/components/EmailTransactionalSection/EmailTransactionalSection.tsx +6 -8
  187. package/src/features/users/components/LoginField/LoginField.tsx +4 -4
  188. package/src/features/users/components/ReassignOrgUnitDrawer/ReassignOrgUnitDrawer.tsx +22 -19
  189. package/src/features/users/components/ResetPasswordDrawer/ResetPasswordDrawer.tsx +16 -21
  190. package/src/features/users/components/UpdateUserDrawer/UpdateUserDrawer.tsx +26 -15
  191. package/src/features/users/components/UpdateUserDrawerWithUsername/UpdateUserDrawerWithUsername.tsx +22 -8
  192. package/src/features/users/components/UserDropdownMenu/UserDropdownMenu.tsx +7 -5
  193. package/src/features/users/components/UserFormFields/UserFormFields.tsx +9 -8
  194. package/src/features/users/components/UsersCard/UsersCard.tsx +4 -2
  195. package/src/features/users/layouts/UserDetailsLayout/UserDetailsLayout.tsx +26 -10
  196. package/src/features/users/layouts/UsersLayout/UsersLayout.tsx +12 -8
  197. package/src/pages/accounting-field.tsx +28 -15
  198. package/src/pages/address-details.tsx +37 -26
  199. package/src/pages/addresses.tsx +27 -12
  200. package/src/pages/budgets-details.tsx +25 -15
  201. package/src/pages/budgets.tsx +31 -17
  202. package/src/pages/buyer-organization-manager.tsx +23 -12
  203. package/src/pages/buying-policies.tsx +38 -20
  204. package/src/pages/buying-policy-details.tsx +20 -19
  205. package/src/pages/contracts.tsx +15 -1
  206. package/src/pages/credit-cards.tsx +30 -17
  207. package/src/pages/order-entry.tsx +26 -15
  208. package/src/pages/org-unit-details.tsx +20 -6
  209. package/src/pages/org-units.tsx +20 -6
  210. package/src/pages/payment-groups.tsx +15 -12
  211. package/src/pages/productAssortment.tsx +10 -1
  212. package/src/pages/profile.tsx +14 -1
  213. package/src/pages/role-details.tsx +19 -6
  214. package/src/pages/roles.tsx +27 -14
  215. package/src/pages/user-details.tsx +29 -17
  216. package/src/pages/users.tsx +11 -0
  217. package/vitest.config.ts +13 -0
  218. package/src/features/addresses/constants/messages.ts +0 -8
  219. package/src/features/credit-cards/constants/messages.ts +0 -6
@@ -1,3 +1,5 @@
1
+ import { LOCALIZATION_ENTRY_IDS } from "../localization/constants";
2
+ import { getLocalizationLabelsService } from "../localization/services/get-localization-labels.service";
1
3
  import { validateAccessService } from "../services";
2
4
  import { getBuyerPortalFeatureFlags } from "../services/feature-flags/get-feature-flags.service";
3
5
 
@@ -86,6 +88,12 @@ export const withAuthLoader = async <T>(
86
88
  } catch (error) {
87
89
  console.error("Auth validation failed:", error);
88
90
 
91
+ // Fetch shared labels for the error state; never throws, uses process-local cache.
92
+ const localizationLabels = await getLocalizationLabelsService({
93
+ entryIds: LOCALIZATION_ENTRY_IDS.shared,
94
+ locale: data.locale ?? "",
95
+ });
96
+
89
97
  return {
90
98
  authorized: false,
91
99
  hasError: true,
@@ -103,6 +111,9 @@ export const withAuthLoader = async <T>(
103
111
  errorType: "auth_error",
104
112
  },
105
113
  },
114
+ context: {
115
+ localization: { labels: localizationLabels },
116
+ },
106
117
  };
107
118
  }
108
119
  };
@@ -1,3 +1,5 @@
1
+ import { LOCALIZATION_ENTRY_IDS } from "../localization/constants";
2
+ import { getLocalizationLabelsService } from "../localization/services/get-localization-labels.service";
1
3
  import { logError } from "../services/logger";
2
4
 
3
5
  import { getClientContext } from "./getClientContext";
@@ -77,6 +79,12 @@ export function withLoaderErrorBoundary<TQuery, TReturn>(
77
79
  };
78
80
  }
79
81
 
82
+ // Fetch shared labels for the error state; never throws, uses process-local cache.
83
+ const localizationLabels = await getLocalizationLabelsService({
84
+ entryIds: LOCALIZATION_ENTRY_IDS.shared,
85
+ locale: data.locale ?? "",
86
+ });
87
+
80
88
  // Serialize query to ensure it's JSON-safe (use null instead of undefined)
81
89
  const serializedQuery = data.query
82
90
  ? JSON.parse(JSON.stringify(data.query))
@@ -104,6 +112,7 @@ export function withLoaderErrorBoundary<TQuery, TReturn>(
104
112
  currentOrgUnit: null,
105
113
  currentContract: null,
106
114
  currentUser: null,
115
+ localization: { labels: localizationLabels },
107
116
  },
108
117
  data: null,
109
118
  };
@@ -1,5 +1,7 @@
1
1
  import { type ComponentType } from "react";
2
2
 
3
+ import { withLocalization } from "../localization/withLocalization";
4
+
3
5
  import { withAuth } from "./withAuth";
4
6
  import { withBuyerPortal } from "./withBuyerPortal";
5
7
 
@@ -12,9 +14,18 @@ type ProviderHOC = (Component: ComponentType<any>) => ComponentType<any>;
12
14
 
13
15
  /**
14
16
  * Default project providers applied to all pages.
15
- * Order: right to left (like pipe/compose)
17
+ * Order: right to left (like pipe/compose).
18
+ * Resulting tree: withAuth › withLocalization › withBuyerPortal › Component
19
+ *
20
+ * withLocalization is placed before withBuyerPortal so it:
21
+ * 1. Receives `context` (withBuyerPortal strips it before rendering its child).
22
+ * 2. Wraps BuyerPortalProvider (and its LoadingTabsLayout), enabling localization in loading states.
16
23
  */
17
- const projectProviders: ProviderHOC[] = [withAuth, withBuyerPortal];
24
+ const projectProviders: ProviderHOC[] = [
25
+ withAuth,
26
+ withLocalization,
27
+ withBuyerPortal,
28
+ ];
18
29
 
19
30
  /**
20
31
  * HOC that applies all default project providers.
@@ -2,7 +2,8 @@ import { useState } from "react";
2
2
 
3
3
  import { useRouter } from "next/router";
4
4
 
5
- import { Button, useUI } from "@faststore/ui";
5
+ import { useLink_unstable as useLink } from "@faststore/core/experimental";
6
+ import { Button, Link, useUI } from "@faststore/ui";
6
7
 
7
8
  import { RoleData } from "../../../roles/types";
8
9
  import {
@@ -13,10 +14,10 @@ import {
13
14
  InputText,
14
15
  } from "../../../shared/components";
15
16
  import { useAnalytics } from "../../../shared/hooks";
17
+ import { useLocalization } from "../../../shared/localization/LocalizationContext";
16
18
  import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
17
19
  import { isValidEmail } from "../../../shared/utils";
18
20
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
19
- import { CHANGES_TIMEOUT_MESSAGE } from "../../../shared/utils/constants";
20
21
  import {
21
22
  maskPhoneNumber,
22
23
  normalizePhoneNumber,
@@ -38,6 +39,8 @@ export const CreateUserDrawer = ({
38
39
  }: CreateUserDrawerProps) => {
39
40
  const { pushToast } = useUI();
40
41
  const router = useRouter();
42
+ const { t } = useLocalization();
43
+ const { resolveLink } = useLink();
41
44
  const { trackEntityCreated, trackEntityCreateError } = useAnalytics({
42
45
  entityType: "user",
43
46
  defaultTimerName: "user_creation",
@@ -98,7 +101,9 @@ export const CreateUserDrawer = ({
98
101
  });
99
102
 
100
103
  pushToast({
101
- message: `User successfully added\n${CHANGES_TIMEOUT_MESSAGE}`,
104
+ message: `${t("users.create.toasts.userSuccessfullyAdded")}\n${t(
105
+ "shared.messages.changesTimeout"
106
+ )}`,
102
107
  status: "INFO",
103
108
  icon: (
104
109
  <button
@@ -111,7 +116,7 @@ export const CreateUserDrawer = ({
111
116
  });
112
117
  }}
113
118
  >
114
- View
119
+ {t("shared.buttons.view")}
115
120
  </button>
116
121
  ),
117
122
  });
@@ -218,10 +223,10 @@ export const CreateUserDrawer = ({
218
223
  data-fs-bp-create-user-drawer-back-icon
219
224
  />
220
225
  </button>
221
- User cannot be added
226
+ {t("users.create.drawerTitleUserCannotBeAdded")}
222
227
  </>
223
228
  ) : (
224
- "Add User"
229
+ t("users.create.drawerTitle")
225
230
  )
226
231
  }
227
232
  onClose={close}
@@ -232,16 +237,16 @@ export const CreateUserDrawer = ({
232
237
  {hasRolesError ? (
233
238
  <div data-fs-bp-create-user-error-state>
234
239
  <Icon name="Warning" height={48} width={48} />
235
- <h3>Something went wrong</h3>
236
- <p>The add user form could not be loaded.</p>
240
+ <h3>{t("shared.messages.somethingWentWrong")}</h3>
241
+ <p>{t("users.create.errors.formCouldNotBeLoaded")}</p>
237
242
  <Button variant="secondary" onClick={handleRetryRoles}>
238
- Try again
243
+ {t("shared.buttons.tryAgain")}
239
244
  </Button>
240
245
  </div>
241
246
  ) : (
242
247
  <>
243
248
  <InputText
244
- label="Full Name"
249
+ label={t("users.forms.fullName")}
245
250
  value={name}
246
251
  hasError={isTouched && !name?.trim()}
247
252
  onChange={(event) => updateField("name", event.target.value)}
@@ -249,11 +254,11 @@ export const CreateUserDrawer = ({
249
254
 
250
255
  <ErrorMessage
251
256
  show={isTouched && !name?.trim()}
252
- message="Full name is required"
257
+ message={t("users.validation.fullNameRequired")}
253
258
  />
254
259
 
255
260
  <InputText
256
- label="E-mail"
261
+ label={t("users.forms.email")}
257
262
  value={email}
258
263
  wrapperProps={{ style: { marginTop: 16, marginBottom: 16 } }}
259
264
  hasError={isTouched && emailInvalid}
@@ -264,15 +269,16 @@ export const CreateUserDrawer = ({
264
269
  <ErrorMessage
265
270
  show={isTouched && emailInvalid}
266
271
  message={
267
- !email.trim() ? "E-mail is required" : "E-mail is invalid"
272
+ !email.trim()
273
+ ? t("users.validation.emailRequired")
274
+ : t("users.validation.emailInvalid")
268
275
  }
269
276
  />
270
277
 
271
278
  <InputText
272
- label="Phone number (optional)"
279
+ label={t("users.forms.phoneNumberOptional")}
273
280
  value={maskPhoneNumber(phone, "USA")}
274
281
  onChange={(event) =>
275
- // TODO: Update this when implementing i18n
276
282
  updateField(
277
283
  "phone",
278
284
  normalizePhoneNumber(event.target.value)
@@ -281,7 +287,9 @@ export const CreateUserDrawer = ({
281
287
  />
282
288
 
283
289
  <div data-fs-bp-create-user-roles>
284
- <span data-fs-bp-create-user-roles-label>Roles</span>
290
+ <span data-fs-bp-create-user-roles-label>
291
+ {t("users.forms.roles")}
292
+ </span>
285
293
 
286
294
  {rolesOptions &&
287
295
  rolesOptions.map((role) => {
@@ -316,7 +324,7 @@ export const CreateUserDrawer = ({
316
324
  </BasicDrawer.Body>
317
325
  <BasicDrawer.Footer>
318
326
  <BasicDrawer.Button variant="ghost" onClick={close}>
319
- Cancel
327
+ {t("shared.buttons.cancel")}
320
328
  </BasicDrawer.Button>
321
329
  <BasicDrawer.Button
322
330
  variant="confirm"
@@ -324,7 +332,7 @@ export const CreateUserDrawer = ({
324
332
  onClick={handleConfirmClick}
325
333
  isLoading={isAddUserToOrgUnitLoading}
326
334
  >
327
- Add
335
+ {t("users.create.buttons.add")}
328
336
  </BasicDrawer.Button>
329
337
  </BasicDrawer.Footer>
330
338
  </>
@@ -332,23 +340,27 @@ export const CreateUserDrawer = ({
332
340
  {drawerState === "USER_ALREADY_EXISTS" && (
333
341
  <>
334
342
  <BasicDrawer.Body data-fs-bp-create-user-drawer-body>
335
- <p>This user is assigned to another organizational unit.</p>
343
+ <p>{t("users.create.messages.userAssignedToAnotherUnit")}</p>
336
344
  <br />
337
345
  <p>
338
- Users can only belong to one organizational unit at a time. To add
339
- <a
340
- href={`/user/${userAlreadyInUse?.id}`}
341
- >{` ${userAlreadyInUse?.name}`}</a>{" "}
342
- to {orgUnitName}, go to their profile and move them from
343
- {` ${userAlreadyInUse?.orgUnit}`}.
346
+ {t("users.create.messages.moveUserFromAnotherUnit", [
347
+ <Link
348
+ key="user-name"
349
+ href={resolveLink(`/user/${userAlreadyInUse?.id}`)}
350
+ >
351
+ {userAlreadyInUse?.name}
352
+ </Link>,
353
+ orgUnitName,
354
+ userAlreadyInUse?.orgUnit,
355
+ ])}
344
356
  </p>
345
357
  </BasicDrawer.Body>
346
358
  <BasicDrawer.Footer>
347
359
  <BasicDrawer.Button variant="ghost" onClick={close}>
348
- Cancel
360
+ {t("shared.buttons.cancel")}
349
361
  </BasicDrawer.Button>
350
362
  <BasicDrawer.Button variant="confirm" onClick={close}>
351
- Ok
363
+ {t("shared.buttons.ok")}
352
364
  </BasicDrawer.Button>
353
365
  </BasicDrawer.Footer>
354
366
  </>
@@ -11,10 +11,10 @@ import {
11
11
  Icon,
12
12
  } from "../../../shared/components";
13
13
  import { useAnalytics, useBuyerPortal } from "../../../shared/hooks";
14
+ import { useLocalization } from "../../../shared/localization/LocalizationContext";
14
15
  import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
15
16
  import { isValidEmail } from "../../../shared/utils";
16
17
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
17
- import { CHANGES_TIMEOUT_MESSAGE } from "../../../shared/utils/constants";
18
18
  import { normalizePhoneNumber } from "../../../shared/utils/phoneNumber";
19
19
  import { useAddUserToOrgUnit, useResetPassword } from "../../hooks";
20
20
  import { detectLoginType } from "../../utils/detectLoginType";
@@ -48,6 +48,7 @@ export const CreateUserDrawerWithUsername = ({
48
48
  const { pushToast } = useUI();
49
49
  const router = useRouter();
50
50
  const { featureFlags } = useBuyerPortal();
51
+ const { t } = useLocalization();
51
52
  const { trackEntityCreated, trackEntityCreateError } = useAnalytics({
52
53
  entityType: "user",
53
54
  defaultTimerName: "user_creation",
@@ -149,13 +150,12 @@ export const CreateUserDrawerWithUsername = ({
149
150
 
150
151
  const handleResetPasswordError = useCallback(() => {
151
152
  pushToast({
152
- message:
153
- "Failed to generate access code. Please try resetting the password later.",
153
+ message: t("users.create.errors.failedToGenerateAccessCode"),
154
154
  status: "ERROR",
155
155
  });
156
156
  onCreate?.();
157
157
  close();
158
- }, [pushToast, onCreate, close]);
158
+ }, [pushToast, onCreate, close, t]);
159
159
 
160
160
  const { resetPassword, isResetPasswordLoading } = useResetPassword({
161
161
  onSuccess: handleResetPasswordSuccess,
@@ -183,8 +183,10 @@ export const CreateUserDrawerWithUsername = ({
183
183
  }
184
184
 
185
185
  pushToast({
186
- title: "User added successfully",
187
- message: `An access code has been sent to [${effectiveEmail}](mailto:${effectiveEmail}) for first-time login.\n${CHANGES_TIMEOUT_MESSAGE}`,
186
+ title: t("users.create.toasts.userAddedSuccessfully"),
187
+ message: `${t("users.create.toasts.accessCodeSent", [
188
+ `[${email}](mailto:${email})`,
189
+ ])}\n${t("shared.messages.changesTimeout")}`,
188
190
  status: "INFO",
189
191
  icon: (
190
192
  <button
@@ -197,7 +199,7 @@ export const CreateUserDrawerWithUsername = ({
197
199
  });
198
200
  }}
199
201
  >
200
- View
202
+ {t("shared.buttons.view")}
201
203
  </button>
202
204
  ),
203
205
  });
@@ -231,14 +233,15 @@ export const CreateUserDrawerWithUsername = ({
231
233
  if (error.code === "EMAIL_ALREADY_EXISTS") {
232
234
  setSharedEmailData({
233
235
  email: loginType === "email" ? login : email,
234
- existingUserName: error.existingUserName || "another user",
236
+ existingUserName:
237
+ error.existingUserName || t("users.create.messages.anotherUser"),
235
238
  });
236
239
  setDrawerState("CONFIRM_SHARED_EMAIL");
237
240
  return;
238
241
  }
239
242
 
240
243
  pushToast({
241
- message: error.message || "An error occurred while creating the user",
244
+ message: error.message || t("users.create.errors.failedToCreateUser"),
242
245
  status: "ERROR",
243
246
  });
244
247
  },
@@ -259,9 +262,15 @@ export const CreateUserDrawerWithUsername = ({
259
262
  try {
260
263
  await navigator.clipboard.writeText(accessToken);
261
264
  setHasTokenBeenCopied(true);
262
- pushToast({ message: "Access code copied to clipboard", status: "INFO" });
265
+ pushToast({
266
+ message: t("users.reset.toasts.accessCodeCopied"),
267
+ status: "INFO",
268
+ });
263
269
  } catch {
264
- pushToast({ message: "Failed to copy access code", status: "ERROR" });
270
+ pushToast({
271
+ message: t("users.reset.toasts.failedToCopyAccessCode"),
272
+ status: "ERROR",
273
+ });
265
274
  }
266
275
  };
267
276
 
@@ -293,13 +302,13 @@ export const CreateUserDrawerWithUsername = ({
293
302
  data-fs-bp-create-user-drawer-back-icon
294
303
  />
295
304
  </button>
296
- Confirm shared email
305
+ {t("users.create.drawerTitleConfirmSharedEmail")}
297
306
  </>
298
307
  );
299
308
  case "ACCESS_TOKEN_DISPLAY":
300
309
  return "";
301
310
  default:
302
- return "Add User";
311
+ return t("users.create.drawerTitle");
303
312
  }
304
313
  };
305
314
 
@@ -313,10 +322,10 @@ export const CreateUserDrawerWithUsername = ({
313
322
  {hasRolesError ? (
314
323
  <div data-fs-bp-create-user-error-state>
315
324
  <Icon name="Warning" height={48} width={48} />
316
- <h3>Something went wrong</h3>
317
- <p>The add user form could not be loaded.</p>
325
+ <h3>{t("shared.errors.somethingWentWrong")}</h3>
326
+ <p>{t("users.create.errors.formCouldNotBeLoaded")}</p>
318
327
  <Button variant="secondary" onClick={() => router.reload()}>
319
- Try again
328
+ {t("shared.buttons.tryAgain")}
320
329
  </Button>
321
330
  </div>
322
331
  ) : (
@@ -334,7 +343,7 @@ export const CreateUserDrawerWithUsername = ({
334
343
  </BasicDrawer.Body>
335
344
  <BasicDrawer.Footer>
336
345
  <BasicDrawer.Button variant="ghost" onClick={close}>
337
- Cancel
346
+ {t("shared.buttons.cancel")}
338
347
  </BasicDrawer.Button>
339
348
  <BasicDrawer.Button
340
349
  variant="confirm"
@@ -344,7 +353,7 @@ export const CreateUserDrawerWithUsername = ({
344
353
  onClick={handleConfirmClick}
345
354
  isLoading={isAddUserToOrgUnitLoading || isResetPasswordLoading}
346
355
  >
347
- Add
356
+ {t("users.create.buttons.add")}
348
357
  </BasicDrawer.Button>
349
358
  </BasicDrawer.Footer>
350
359
  </>
@@ -355,28 +364,28 @@ export const CreateUserDrawerWithUsername = ({
355
364
  <BasicDrawer.Body data-fs-bp-create-user-shared-email-body>
356
365
  <div data-fs-bp-create-user-shared-email-warning>
357
366
  <Icon name="Warning" height={48} width={48} />
358
- <h3>This email is already registered</h3>
367
+ <h3>{t("users.create.messages.emailAlreadyRegistered")}</h3>
359
368
  </div>
360
- <p>
361
- The email <strong>{sharedEmailData.email}</strong> is already
362
- registered for another user (
363
- <strong>{sharedEmailData.existingUserName}</strong>).
364
- </p>
365
- <p>
366
- Are you sure you want to continue? If you proceed, a temporary
367
- access code will be generated for the new user.
369
+ <p data-fs-bp-create-user-shared-email-registered-text>
370
+ {t("users.create.messages.emailRegisteredForAnotherUser", [
371
+ <strong key="email">{sharedEmailData.email}</strong>,
372
+ <strong key="username">
373
+ {sharedEmailData.existingUserName}
374
+ </strong>,
375
+ ])}
368
376
  </p>
377
+ <p>{t("users.create.messages.confirmSharedEmailContinue")}</p>
369
378
  </BasicDrawer.Body>
370
379
  <BasicDrawer.Footer>
371
380
  <BasicDrawer.Button variant="ghost" onClick={backToCreateUser}>
372
- Cancel
381
+ {t("shared.buttons.cancel")}
373
382
  </BasicDrawer.Button>
374
383
  <BasicDrawer.Button
375
384
  variant="confirm"
376
385
  onClick={handleConfirmSharedEmail}
377
386
  isLoading={isAddUserToOrgUnitLoading}
378
387
  >
379
- Continue
388
+ {t("shared.buttons.continue")}
380
389
  </BasicDrawer.Button>
381
390
  </BasicDrawer.Footer>
382
391
  </>
@@ -387,17 +396,10 @@ export const CreateUserDrawerWithUsername = ({
387
396
  <BasicDrawer.Body data-fs-bp-create-user-access-token-body>
388
397
  <AccessTokenDisplay
389
398
  accessToken={accessToken}
390
- title="Password reset successfully"
399
+ title={t("users.reset.messages.passwordResetSuccessfully")}
391
400
  description={
392
401
  <p>
393
- A temporary access code has been generated. <br />
394
- Share it with the user, as they have no individual email
395
- registered.
396
- <br />
397
- <br />
398
- The code expires in 12 hours. Copy it before closing this
399
- window. Once closed, access will be lost and a password reset
400
- will be required.
402
+ {t("users.reset.messages.accessCodeGeneratedDescription")}
401
403
  </p>
402
404
  }
403
405
  hasBeenCopied={hasTokenBeenCopied}
@@ -410,7 +412,7 @@ export const CreateUserDrawerWithUsername = ({
410
412
  onClick={handleCloseAccessTokenModal}
411
413
  disabled={!hasTokenBeenCopied}
412
414
  >
413
- Done
415
+ {t("shared.buttons.done")}
414
416
  </BasicDrawer.Button>
415
417
  </BasicDrawer.Footer>
416
418
  </>
@@ -9,9 +9,9 @@ import {
9
9
  type BasicDrawerProps,
10
10
  } from "../../../shared/components";
11
11
  import { useAnalytics } from "../../../shared/hooks";
12
+ import { useLocalization } from "../../../shared/localization/LocalizationContext";
12
13
  import { ANALYTICS_EVENTS } from "../../../shared/services/logger/analytics/constants";
13
14
  import { buyerPortalRoutes } from "../../../shared/utils/buyerPortalRoutes";
14
- import { CHANGES_TIMEOUT_MESSAGE } from "../../../shared/utils/constants";
15
15
  import { useRemoveUserFromOrgUnit } from "../../hooks";
16
16
 
17
17
  export type DeleteUserDrawerProps = Omit<BasicDrawerProps, "children"> & {
@@ -30,6 +30,7 @@ export const DeleteUserDrawer = ({
30
30
 
31
31
  const { pushToast } = useUI();
32
32
  const { orgUnit } = useOrgUnitByUser(user.id);
33
+ const { t } = useLocalization();
33
34
  const { trackEvent } = useAnalytics({
34
35
  entityType: "user",
35
36
  entityId: user.id,
@@ -46,7 +47,9 @@ export const DeleteUserDrawer = ({
46
47
  });
47
48
 
48
49
  pushToast({
49
- message: `User successfully deleted\n${CHANGES_TIMEOUT_MESSAGE}`,
50
+ message: `${t("users.delete.toasts.userSuccessfullyDeleted")}\n${t(
51
+ "shared.messages.changesTimeout"
52
+ )}`,
50
53
  status: "INFO",
51
54
  });
52
55
  onDelete?.();
@@ -76,7 +79,7 @@ export const DeleteUserDrawer = ({
76
79
  });
77
80
 
78
81
  pushToast({
79
- message: "An error occurred while deleting the user",
82
+ message: t("users.delete.errors.failedToDeleteUser"),
80
83
  status: "ERROR",
81
84
  });
82
85
  },
@@ -86,32 +89,33 @@ export const DeleteUserDrawer = ({
86
89
 
87
90
  return (
88
91
  <BasicDrawer {...otherProps} data-fs-bp-delete-user-drawer close={close}>
89
- <BasicDrawer.Heading title="Delete user" onClose={close} />
92
+ <BasicDrawer.Heading
93
+ title={t("users.delete.drawerTitle")}
94
+ onClose={close}
95
+ />
90
96
  <BasicDrawer.Body data-fs-bp-delete-user-drawer-body>
91
97
  <p>
92
- Permanently delete{" "}
93
- <a
94
- href={buyerPortalRoutes.userDetails({
95
- orgUnitId: orgUnit?.id || "",
96
- userId: user.id,
97
- })}
98
- data-fs-bp-delete-user-drawer-user-name
99
- >
100
- {user.name}
101
- </a>
102
- ?
98
+ {t("users.delete.messages.confirmDeleteUser", [
99
+ <a
100
+ key="user-name"
101
+ href={buyerPortalRoutes.userDetails({
102
+ orgUnitId: orgUnit?.id || "",
103
+ userId: user.id,
104
+ })}
105
+ data-fs-bp-delete-user-drawer-user-name
106
+ >
107
+ {user.name}
108
+ </a>,
109
+ ])}
103
110
  </p>
104
111
  <br />
105
- <p>
106
- Deleting this user will permanently remove all its data, but usage
107
- history will be kept for audit. This action cannot be undone.
108
- </p>
112
+ <p>{t("users.delete.messages.deleteWarning")}</p>
109
113
  <br />
110
- <p>Confirm by typing the user name below:</p>
114
+ <p>{t("users.delete.messages.confirmByTypingUserName")}</p>
111
115
  <br />
112
116
 
113
117
  <InputText
114
- label="User name"
118
+ label={t("users.delete.forms.userName")}
115
119
  value={userNameConfirmation}
116
120
  onChange={(event) =>
117
121
  setUserNameConfirmation(event.currentTarget.value)
@@ -121,7 +125,7 @@ export const DeleteUserDrawer = ({
121
125
 
122
126
  <BasicDrawer.Footer>
123
127
  <BasicDrawer.Button variant="ghost" onClick={close}>
124
- Cancel
128
+ {t("shared.buttons.cancel")}
125
129
  </BasicDrawer.Button>
126
130
  <BasicDrawer.Button
127
131
  variant="danger"
@@ -129,7 +133,7 @@ export const DeleteUserDrawer = ({
129
133
  onClick={handleDeleteClick}
130
134
  disabled={!isDeleteButtonEnabled}
131
135
  >
132
- Delete
136
+ {t("shared.buttons.delete")}
133
137
  </BasicDrawer.Button>
134
138
  </BasicDrawer.Footer>
135
139
  </BasicDrawer>
@@ -1,6 +1,7 @@
1
1
  import { CheckboxField } from "@faststore/ui";
2
2
 
3
3
  import { ErrorMessage, InputText } from "../../../shared/components";
4
+ import { useLocalization } from "../../../shared/localization/LocalizationContext";
4
5
  import { isValidEmail } from "../../../shared/utils";
5
6
 
6
7
  export interface EmailTransactionalSectionProps {
@@ -11,10 +12,6 @@ export interface EmailTransactionalSectionProps {
11
12
  isTouched: boolean;
12
13
  }
13
14
 
14
- const USE_EMAIL_LABEL = "Use this e-mail for transactional notifications";
15
- const TRANSACTIONAL_EMAIL_REQUIRED_MSG = "Transactional e-mail is required";
16
- const TRANSACTIONAL_EMAIL_INVALID_MSG = "Transactional e-mail is invalid";
17
-
18
15
  export const EmailTransactionalSection = ({
19
16
  useLoginAsTransactional,
20
17
  onCheckboxChange,
@@ -22,6 +19,7 @@ export const EmailTransactionalSection = ({
22
19
  onTransactionalEmailChange,
23
20
  isTouched,
24
21
  }: EmailTransactionalSectionProps) => {
22
+ const { t } = useLocalization();
25
23
  const trimmed = transactionalEmail.trim();
26
24
  const isMissing = !trimmed;
27
25
  const isInvalid = Boolean(trimmed) && !isValidEmail(trimmed);
@@ -32,7 +30,7 @@ export const EmailTransactionalSection = ({
32
30
  <div data-fs-bp-email-transactional-section>
33
31
  <CheckboxField
34
32
  id="use-login-as-transactional"
35
- label={USE_EMAIL_LABEL}
33
+ label={t("users.forms.useEmailForNotifications")}
36
34
  checked={useLoginAsTransactional}
37
35
  onChange={(event) => onCheckboxChange(event.target.checked)}
38
36
  />
@@ -40,7 +38,7 @@ export const EmailTransactionalSection = ({
40
38
  {!useLoginAsTransactional && (
41
39
  <>
42
40
  <InputText
43
- label="Transactional E-mail"
41
+ label={t("users.labels.transactionalEmail")}
44
42
  value={transactionalEmail}
45
43
  type="email"
46
44
  hasError={showError}
@@ -56,8 +54,8 @@ export const EmailTransactionalSection = ({
56
54
  show
57
55
  message={
58
56
  isMissing
59
- ? TRANSACTIONAL_EMAIL_REQUIRED_MSG
60
- : TRANSACTIONAL_EMAIL_INVALID_MSG
57
+ ? t("users.validation.emailTransactionalRequired")
58
+ : t("users.validation.emailTransactionalInvalid")
61
59
  }
62
60
  />
63
61
  </div>