diff --git a/CRM/Contribute/Form/Task/PDFLetter.php b/CRM/Contribute/Form/Task/PDFLetter.php
index e6b639f09e7c241809da57b7654658c45c233599..23df8d1a916041bcae669750b18629cf6f4d9f09 100644
--- a/CRM/Contribute/Form/Task/PDFLetter.php
+++ b/CRM/Contribute/Form/Task/PDFLetter.php
@@ -584,9 +584,7 @@ class CRM_Contribute_Form_Task_PDFLetter extends CRM_Contribute_Form_Task {
         foreach ($tokenProcessor->getRows() as $row) {
           $resolvedTokens[$token][$row->context['contributionId']] = $row->render($token);
         }
-        // We've resolved the value for each row - resorting to swapping them out
-        // with the old function.
-        $html_message = CRM_Utils_Token::token_replace('contribution', $token, implode($separator, $resolvedTokens[$token]), $html_message);
+        $html_message = str_replace('{contribution.' . $token . '}', implode($separator, $resolvedTokens[$token]), $html_message);
       }
     }
     $tokenContext['contributionId'] = $contributionID;
diff --git a/CRM/Contribute/WorkflowMessage/RecurringEdit/AlexCancelled.ex.php b/CRM/Contribute/WorkflowMessage/RecurringEdit/AlexCancelled.ex.php
index 057244938a4fd0a4a56a501777f070a49f4edc1e..846f99b1b0d6c31370c64fec26895b297e570caf 100644
--- a/CRM/Contribute/WorkflowMessage/RecurringEdit/AlexCancelled.ex.php
+++ b/CRM/Contribute/WorkflowMessage/RecurringEdit/AlexCancelled.ex.php
@@ -20,7 +20,7 @@ class CRM_Contribute_WorkflowMessage_RecurringEdit_AlexCancelled extends \Civi\W
     $example['asserts'] = [
       'default' => [
         ['for' => 'subject', 'regex' => '/Recurring Contribution Update.*Alex/'],
-        ['for' => 'text', 'regex' => '/Recurring contribution is for € 5,990.99, every 2 year.s. for 24 installments/'],
+        ['for' => 'text', 'regex' => '/Recurring contribution is for €5,990.99, every 2 year.s. for 24 installments/'],
       ],
     ];
   }
diff --git a/CRM/Contribute/WorkflowMessage/RecurringEdit/BarbPending.ex.php b/CRM/Contribute/WorkflowMessage/RecurringEdit/BarbPending.ex.php
index d6df8cb69ac9460390dabaec2dddfafd1ef9311e..6c19f770acadf44c1686600a837c160c7e8e3981 100644
--- a/CRM/Contribute/WorkflowMessage/RecurringEdit/BarbPending.ex.php
+++ b/CRM/Contribute/WorkflowMessage/RecurringEdit/BarbPending.ex.php
@@ -21,7 +21,7 @@ class CRM_Contribute_WorkflowMessage_RecurringEdit_BarbPending extends \Civi\Wor
     $example['asserts'] = [
       'default' => [
         ['for' => 'subject', 'regex' => '/Recurring Contribution Update.*Barb/'],
-        ['for' => 'text', 'regex' => '/Recurring contribution is for € 5,990.99, every 2 year.s. for 24 installments/'],
+        ['for' => 'text', 'regex' => '/Recurring contribution is for €5,990.99, every 2 year.s. for 24 installments/'],
       ],
     ];
   }
diff --git a/CRM/Core/EntityTokens.php b/CRM/Core/EntityTokens.php
index c1cb2fcbc414ac69a8eed4aa3b8981d5cea2a0f3..f995bc3650502bb3a0ec28706e0b99fb4066b1ec 100644
--- a/CRM/Core/EntityTokens.php
+++ b/CRM/Core/EntityTokens.php
@@ -16,6 +16,7 @@ use Civi\Token\Event\TokenValueEvent;
 use Civi\Token\TokenRow;
 use Civi\ActionSchedule\Event\MailingQueryEvent;
 use Civi\Token\TokenProcessor;
+use Brick\Money\Money;
 
 /**
  * Class CRM_Core_EntityTokens
@@ -123,8 +124,15 @@ class CRM_Core_EntityTokens extends AbstractTokenSubscriber {
       return $row->customToken($entity, \CRM_Core_BAO_CustomField::getKeyID($field), $this->getFieldValue($row, 'id'));
     }
     if ($this->isMoneyField($field)) {
+      $currency = $this->getCurrency($row);
+      if (!$currency) {
+        // too hard basket for now - just do what we always did.
+        return $row->format('text/plain')->tokens($entity, $field,
+          \CRM_Utils_Money::format($fieldValue, $currency));
+      }
       return $row->format('text/plain')->tokens($entity, $field,
-        \CRM_Utils_Money::format($fieldValue, $this->getCurrency($row)));
+        Money::of($fieldValue, $currency));
+
     }
     if ($this->isDateField($field)) {
       try {
diff --git a/Civi/Token/TokenCompatSubscriber.php b/Civi/Token/TokenCompatSubscriber.php
index 33e394f3cdfca0522db59454b222ab153c4bddd1..6274d8f29c399e72ee6d9bfe17ee78b0559f8c1e 100644
--- a/Civi/Token/TokenCompatSubscriber.php
+++ b/Civi/Token/TokenCompatSubscriber.php
@@ -3,6 +3,7 @@ namespace Civi\Token;
 
 use Civi\Token\Event\TokenRenderEvent;
 use Civi\Token\Event\TokenValueEvent;
+use Money\Money;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 
 /**
@@ -69,7 +70,10 @@ class TokenCompatSubscriber implements EventSubscriberInterface {
     if ($useSmarty) {
       $smartyVars = [];
       foreach ($e->context['smartyTokenAlias'] ?? [] as $smartyName => $tokenName) {
-        $smartyVars[$smartyName] = \CRM_Utils_Array::pathGet($e->row->tokens, explode('.', $tokenName));
+        $smartyVars[$smartyName] = \CRM_Utils_Array::pathGet($e->row->tokens, explode('.', $tokenName), $e->context['locale'] ?? NULL);
+        if ($smartyVars[$smartyName] instanceof \Brick\Money\Money) {
+          $smartyVars[$smartyName] = \Civi::format()->money($smartyVars[$smartyName]->getAmount(), $smartyVars[$smartyName]->getCurrency());
+        }
       }
       \CRM_Core_Smarty::singleton()->pushScope($smartyVars);
       try {
diff --git a/Civi/Token/TokenProcessor.php b/Civi/Token/TokenProcessor.php
index f2e32add916835563472714784440adbd5ee2d2a..0451b2ae531ea55e71abb5b8623bd357e97d5a37 100644
--- a/Civi/Token/TokenProcessor.php
+++ b/Civi/Token/TokenProcessor.php
@@ -1,6 +1,7 @@
 <?php
 namespace Civi\Token;
 
+use Brick\Money\Money;
 use Civi\Token\Event\TokenRegisterEvent;
 use Civi\Token\Event\TokenRenderEvent;
 use Civi\Token\Event\TokenValueEvent;
@@ -429,7 +430,7 @@ class TokenProcessor {
           '/:"([^"]+)"/' => $enqueue,
         ], $m[3]);
         if ($unmatched) {
-          throw new \CRM_Core_Exception("Malformed token parameters (" . $m[0] . ")");
+          throw new \CRM_Core_Exception('Malformed token parameters (' . $m[0] . ')');
         }
       }
       return $callback($m[0] ?? NULL, $m[1] ?? NULL, $m[2] ?? NULL, $filterParts);
@@ -458,6 +459,10 @@ class TokenProcessor {
       }
     }
 
+    if ($value instanceof Money && $filter === NULL) {
+      $filter = ['crmMoney'];
+    }
+
     switch ($filter[0] ?? NULL) {
       case NULL:
         return $value;
@@ -468,6 +473,11 @@ class TokenProcessor {
       case 'lower':
         return mb_strtolower($value);
 
+      case 'crmMoney':
+        if ($value instanceof Money) {
+          return \Civi::format()->money($value->getAmount(), $value->getCurrency());
+        }
+
       case 'crmDate':
         if ($value instanceof \DateTime) {
           // @todo cludgey.
diff --git a/Civi/Token/TokenRow.php b/Civi/Token/TokenRow.php
index 680e7c0e36936e375a087bb08c0cc967f8489b8b..11be3a3ba1ffdd6eda8b5752de93490a21f070e3 100644
--- a/Civi/Token/TokenRow.php
+++ b/Civi/Token/TokenRow.php
@@ -1,8 +1,11 @@
 <?php
 namespace Civi\Token;
 
+use Brick\Money\Money;
+
 /**
  * Class TokenRow
+ *
  * @package Civi\Token
  *
  * A TokenRow is a helper/stub providing simplified access to the TokenProcessor.
@@ -283,7 +286,7 @@ class TokenRow {
         // HTML => Plain.
         foreach ($htmlTokens as $entity => $values) {
           foreach ($values as $field => $value) {
-            if (!$value instanceof \DateTime) {
+            if (!$value instanceof \DateTime && !$value instanceof Money) {
               $value = html_entity_decode(strip_tags($value));
             }
             if (!isset($textTokens[$entity][$field])) {
diff --git a/api/v3/Membership.php b/api/v3/Membership.php
index 52e64b8b741bf653cf755544d81991aa97c191c9..c7a3b1d5e478cba39c8a0fc6575f83f75a370d92 100644
--- a/api/v3/Membership.php
+++ b/api/v3/Membership.php
@@ -90,9 +90,19 @@ function civicrm_api3_membership_create($params) {
 
   // Calculate membership dates
   // Fixme: This code belongs in the BAO
-  if (!empty($params['num_terms'])) {
+  if (empty($params['id']) || !empty($params['num_terms'])) {
     // If this is a new membership or we have a specified number of terms calculate membership dates.
-    if (!empty($params['id'])) {
+    if (empty($params['id'])) {
+      // This is a new membership, calculate the membership dates.
+      $calcDates = CRM_Member_BAO_MembershipType::getDatesForMembershipType(
+        $params['membership_type_id'],
+        CRM_Utils_Array::value('join_date', $params),
+        CRM_Utils_Array::value('start_date', $params),
+        CRM_Utils_Array::value('end_date', $params),
+        CRM_Utils_Array::value('num_terms', $params, 1)
+      );
+    }
+    else {
       // This is an existing membership, calculate the membership dates after renewal
       // num_terms is treated as a 'special sauce' for is_renewal but this
       // isn't really helpful for completing pendings.
@@ -102,10 +112,10 @@ function civicrm_api3_membership_create($params) {
         CRM_Utils_Array::value('membership_type_id', $params),
         $params['num_terms']
       );
-      foreach (['join_date', 'start_date', 'end_date'] as $date) {
-        if (empty($params[$date]) && isset($calcDates[$date])) {
-          $params[$date] = $calcDates[$date];
-        }
+    }
+    foreach (['join_date', 'start_date', 'end_date'] as $date) {
+      if (empty($params[$date]) && isset($calcDates[$date])) {
+        $params[$date] = $calcDates[$date];
       }
     }
   }
diff --git a/api/v3/Order.php b/api/v3/Order.php
index 0bef6bef79e78b5561ecb2c6adac6d15d9d05ee9..400bef6f1274c6d0cca95acf039026117b6d7f85 100644
--- a/api/v3/Order.php
+++ b/api/v3/Order.php
@@ -304,6 +304,8 @@ function _civicrm_api3_order_delete_spec(array &$params) {
  */
 function _order_create_wrangle_membership_params(array &$membershipParams) {
   $fields = Membership::getFields(FALSE)->execute()->indexBy('name');
+  // Ensure this legacy parameter is not true.
+  $membershipParams['skipStatusCal'] = FALSE;
   foreach ($fields as $fieldName => $field) {
     $customFieldName = 'custom_' . ($field['custom_field_id'] ?? NULL);
     if ($field['type'] === ['Custom'] && isset($membershipParams[$customFieldName])) {
diff --git a/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php b/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php
index b81b0251d7ecbbc6a15619c9a9b74b7a3091ded8..93d700d62405aeabc37ea92700b87afb50ab624e 100644
--- a/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php
+++ b/ext/afform/admin/Civi/AfformAdmin/AfformAdminMeta.php
@@ -124,7 +124,7 @@ class AfformAdminMeta {
     $fields = (array) civicrm_api4($entityName, 'getFields', $params);
 
     // Add implicit joins to search fields
-    if ($params['action'] === 'search') {
+    if ($params['action'] === 'get') {
       foreach (array_reverse($fields, TRUE) as $index => $field) {
         if (!empty($field['fk_entity']) && !$field['options']) {
           $fkLabelField = CoreUtil::getInfoItem($field['fk_entity'], 'label_field');
diff --git a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php
index b2df1daa1b1349f2f32b6973718cc299c294601c..46f4d3279d2380b9f54c4644b3807dac49a208f8 100644
--- a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php
+++ b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php
@@ -162,7 +162,7 @@ class LoadAdminData extends \Civi\Api4\Generic\AbstractAction {
     }
 
     if ($info['definition']['type'] === 'search') {
-      $getFieldsMode = 'search';
+      $getFieldsMode = 'get';
       $displayTags = [];
       if ($newForm) {
         [$searchName, $displayName] = array_pad(explode('.', $this->entity ?? ''), 2, '');
diff --git a/release-notes.md b/release-notes.md
index 3b7ce9a7b7f00d61f5ab09b751f3c1e3f3838312..8c108a0d211c251f5205c230577ef75cfaa20c73 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -15,6 +15,17 @@ Other resources for identifying changes are:
     * https://github.com/civicrm/civicrm-joomla
     * https://github.com/civicrm/civicrm-wordpress
 
+## CiviCRM 5.43.0
+
+Released November 3, 2021
+
+- **[Synopsis](release-notes/5.43.0.md#synopsis)**
+- **[Features](release-notes/5.43.0.md#features)**
+- **[Bugs resolved](release-notes/5.43.0.md#bugs)**
+- **[Miscellany](release-notes/5.43.0.md#misc)**
+- **[Credits](release-notes/5.43.0.md#credits)**
+- **[Feedback](release-notes/5.43.0.md#feedback)**
+
 ## CiviCRM 5.42.0
 
 Released October 6, 2021
diff --git a/release-notes/5.43.0.md b/release-notes/5.43.0.md
new file mode 100644
index 0000000000000000000000000000000000000000..26fb7fa8ed900439c2cae32ac97a65176ea09be6
--- /dev/null
+++ b/release-notes/5.43.0.md
@@ -0,0 +1,772 @@
+# CiviCRM 5.43.0
+
+Released November 3, 2021
+
+- **[Synopsis](#synopsis)**
+- **[Features](#features)**
+- **[Bugs resolved](#bugs)**
+- **[Miscellany](#misc)**
+- **[Credits](#credits)**
+- **[Feedback](#feedback)**
+
+## <a name="synopsis"></a>Synopsis
+
+| *Does this version...?*                                         |         |
+|:--------------------------------------------------------------- |:-------:|
+| Fix security vulnerabilities?                                   |         |
+| Change the database schema?                                     |         |
+| Alter the API?                                                  |         |
+| Require attention to configuration options?                     |         |
+| Fix problems installing or upgrading to a previous version?     |         |
+| Introduce features?                                             |         |
+| Fix bugs?                                                       |         |
+
+## <a name="features"></a>Features
+
+### Core CiviCRM
+
+- **crm- Missing Summary ([21443](https://github.com/civicrm/civicrm-core/pull/21443))**
+
+- **CRM-19236 Missing Summary ([21597](https://github.com/civicrm/civicrm-core/pull/21597))**
+
+## <a name="bugs"></a>Bugs resolved
+
+### Core CiviCRM
+
+- **Afform - fix loading custom fields for search displays ([21792](https://github.com/civicrm/civicrm-core/pull/21792))**
+
+- **Remove case token listing from contact email task ([21787](https://github.com/civicrm/civicrm-core/pull/21787))**
+
+- **Fix another instance of double token rendering ([21788](https://github.com/civicrm/civicrm-core/pull/21788))**
+
+- **Remove call to legacy getTokenDetails ([21786](https://github.com/civicrm/civicrm-core/pull/21786))**
+
+- **Remove extraneous call to legacy token processing in sms task ([21785](https://github.com/civicrm/civicrm-core/pull/21785))**
+
+- **Contact tokens - use metadata & standardised rendering ([21761](https://github.com/civicrm/civicrm-core/pull/21761))**
+
+- **dev/core#2901 Fix send email regression ([21781](https://github.com/civicrm/civicrm-core/pull/21781))**
+
+- **Enotice fix ([21782](https://github.com/civicrm/civicrm-core/pull/21782))**
+
+- **Fix contact tokens class to load using apiv4 ([21780](https://github.com/civicrm/civicrm-core/pull/21780))**
+
+- **[REF] Extract function for re-use ([21778](https://github.com/civicrm/civicrm-core/pull/21778))**
+
+- **(dev/mail#83) message_admin - Cleanup "Preview" dialogs (properly) ([21772](https://github.com/civicrm/civicrm-core/pull/21772))**
+
+- **APIv4 - Minor code cleanup to improve efficiency in CreateApi4RequestSubscriber ([21775](https://github.com/civicrm/civicrm-core/pull/21775))**
+
+- **(dev/mail#83) message_admin - When using "Preview", use the 'locale' from the editing UI ([21773](https://github.com/civicrm/civicrm-core/pull/21773))**
+
+- **(dev/mail#83) message_admin - Save automatically when adding/removing drafts ([21774](https://github.com/civicrm/civicrm-core/pull/21774))**
+
+- **Afform Admin add link icon & template cleanup ([21764](https://github.com/civicrm/civicrm-core/pull/21764))**
+
+- **Remove stray token code ([21763](https://github.com/civicrm/civicrm-core/pull/21763))**
+
+- **[REF] APIv4 - Use event instead of hardcoded list to resolve entityName to className ([21771](https://github.com/civicrm/civicrm-core/pull/21771))**
+
+- **Fix token regression - re-add support for empty tokens ([21756](https://github.com/civicrm/civicrm-core/pull/21756))**
+
+- **[NFC/Unit Test] Remove wombats and bananas from sites/default/files/civicrm/custom ([21768](https://github.com/civicrm/civicrm-core/pull/21768))**
+
+- **dev/core#2836 install flexmailer by default on new installs [token] ([21522](https://github.com/civicrm/civicrm-core/pull/21522))**
+
+- **Reference token metadata internally fix custom tokens label bug ([21767](https://github.com/civicrm/civicrm-core/pull/21767))**
+
+- **[NFC] Add test for new case email url ([21766](https://github.com/civicrm/civicrm-core/pull/21766))**
+
+- **ensure blank note date in UI defaults to current date. ([21717](https://github.com/civicrm/civicrm-core/pull/21717))**
+
+- **[REF] Move getCustomFieldTokens to the tokens class, annotate more deprecations ([21660](https://github.com/civicrm/civicrm-core/pull/21660))**
+
+- **fixes event#64: Send event confirmation to submitted email address ([21669](https://github.com/civicrm/civicrm-core/pull/21669))**
+
+- **Master only regression - fix empty token date ([21704](https://github.com/civicrm/civicrm-core/pull/21704))**
+
+- **[NFC] Afform - Add array shape annotations to FormDataModel ([21765](https://github.com/civicrm/civicrm-core/pull/21765))**
+
+- **Afform - Fix chainSelect to work with anonymous users ([21759](https://github.com/civicrm/civicrm-core/pull/21759))**
+
+- **dev/core#2650 switch contact.individual_prefix tokens to contact.prefix_id:label (former still works) ([21705](https://github.com/civicrm/civicrm-core/pull/21705))**
+
+- **Support participant & membership tokens in send-email tasks ([21745](https://github.com/civicrm/civicrm-core/pull/21745))**
+
+- **Remove function duplicated in error ([21758](https://github.com/civicrm/civicrm-core/pull/21758))**
+
+- **Remove now-obsolete getPseudoTokens ([21760](https://github.com/civicrm/civicrm-core/pull/21760))**
+
+- **fixes core#2874 - Search Builder on State/Province with Primary and IN ([21646](https://github.com/civicrm/civicrm-core/pull/21646))**
+
+- **Tokens - Hide more sophisticated tokens. Refactor to use "$this->tokenMetadata". ([21706](https://github.com/civicrm/civicrm-core/pull/21706))**
+
+- **5.42 ([21755](https://github.com/civicrm/civicrm-core/pull/21755))**
+
+- **Merge 5.42 to master ([21753](https://github.com/civicrm/civicrm-core/pull/21753))**
+
+- **Flush metadata cache on event edit ([21740](https://github.com/civicrm/civicrm-core/pull/21740))**
+
+- **Fix regression from enotice fixes ([21743](https://github.com/civicrm/civicrm-core/pull/21743))**
+
+- **(dev/mail#83) message_admin - Multiple improvements to the "Preview" dialog ([21747](https://github.com/civicrm/civicrm-core/pull/21747))**
+
+- **Fix for dev/core#2885 ([21716](https://github.com/civicrm/civicrm-core/pull/21716))**
+
+- **System status checks only shows 25 messages ([21748](https://github.com/civicrm/civicrm-core/pull/21748))**
+
+- **dev/core#2866 Ignore preferred mail format - send to both ([21676](https://github.com/civicrm/civicrm-core/pull/21676))**
+
+- **Afform - Fix chain-select of contry and address to work on SearchKit forms ([21749](https://github.com/civicrm/civicrm-core/pull/21749))**
+
+- **(dev/core#2638) Civi::format() - Add helper for formatting ([21599](https://github.com/civicrm/civicrm-core/pull/21599))**
+
+- **5.42 to master ([21744](https://github.com/civicrm/civicrm-core/pull/21744))**
+
+- **Fix possibly unefined $form variables in smarty templates ([21735](https://github.com/civicrm/civicrm-core/pull/21735))**
+
+- **#2892 Replace event type token in action schedule changes event.event_type_id to participant.event_type_id:label. But should be event.event_type_id to event.event_type_id:label ([21738](https://github.com/civicrm/civicrm-core/pull/21738))**
+
+- **For latest iteration of case email form, don't fail when there's no To contact ([21737](https://github.com/civicrm/civicrm-core/pull/21737))**
+
+- **Removes duplicate replace on event fee amount. ([21739](https://github.com/civicrm/civicrm-core/pull/21739))**
+
+- **5.42 to master ([21736](https://github.com/civicrm/civicrm-core/pull/21736))**
+
+- **Use Case form for case email action ([21688](https://github.com/civicrm/civicrm-core/pull/21688))**
+
+- **Enotice fix ([21732](https://github.com/civicrm/civicrm-core/pull/21732))**
+
+- **Fixes dev/core#2888 SearchKit download CSV broken ([21724](https://github.com/civicrm/civicrm-core/pull/21724))**
+
+- **[NFC] Unit test fixes for the problem of quickform rules going missing ([21725](https://github.com/civicrm/civicrm-core/pull/21725))**
+
+- **Enotice fixes ([21723](https://github.com/civicrm/civicrm-core/pull/21723))**
+
+- **fixes financial#181 - don't crash when displaying recurring contributions whose 'template' has no line items ([21729](https://github.com/civicrm/civicrm-core/pull/21729))**
+
+- **SearchKit - tweak button styles for shorditch ([21726](https://github.com/civicrm/civicrm-core/pull/21726))**
+
+- **(dev/core#2766) provide way to distinguish the core and custom fields… ([21728](https://github.com/civicrm/civicrm-core/pull/21728))**
+
+- **REF - Remove non-functional code from APIv3 ([21727](https://github.com/civicrm/civicrm-core/pull/21727))**
+
+- **Add participant tokens to pdf task ([21695](https://github.com/civicrm/civicrm-core/pull/21695))**
+
+- **Afform - Use search display name as field prefix for url-based field defaults ([21645](https://github.com/civicrm/civicrm-core/pull/21645))**
+
+- **Towards full metadata - fully declare 'bespoke' tokens ([21713](https://github.com/civicrm/civicrm-core/pull/21713))**
+
+- **SearchKit - Sortable column fixes/improvements ([21720](https://github.com/civicrm/civicrm-core/pull/21720))**
+
+- **Error about count() on New Email ([21714](https://github.com/civicrm/civicrm-core/pull/21714))**
+
+- **APIv4 - Add Contact.age_years extra field to make age calculations easy ([21718](https://github.com/civicrm/civicrm-core/pull/21718))**
+
+- **flexmailer - Update `[CiviMail Draft]` prefix to match BAO behavior ([21715](https://github.com/civicrm/civicrm-core/pull/21715))**
+
+- **message_admin Style fixes ([21712](https://github.com/civicrm/civicrm-core/pull/21712))**
+
+- **Add missing ts ([21711](https://github.com/civicrm/civicrm-core/pull/21711))**
+
+- **Improve test readability, use schema labels for membership tokens ([21708](https://github.com/civicrm/civicrm-core/pull/21708))**
+
+- **message_admin - Fix quirk when using "Create Draft" ([21700](https://github.com/civicrm/civicrm-core/pull/21700))**
+
+- **NFC - Update code comments ([21675](https://github.com/civicrm/civicrm-core/pull/21675))**
+
+- **Enotice tpl fix ([21689](https://github.com/civicrm/civicrm-core/pull/21689))**
+
+- **fixes core#2881 - APIv3 replace only replaces the first 25 records ([21681](https://github.com/civicrm/civicrm-core/pull/21681))**
+
+- **Function cleanup following move to non-static function ([21693](https://github.com/civicrm/civicrm-core/pull/21693))**
+
+- **enotice fix ([21702](https://github.com/civicrm/civicrm-core/pull/21702))**
+
+- **APIv4 - Give every SQL expression a title ([21691](https://github.com/civicrm/civicrm-core/pull/21691))**
+
+- **message_admin - Add titles/hints to hyperlinks ([21698](https://github.com/civicrm/civicrm-core/pull/21698))**
+
+- ** dev/core#348 Participant tokens on scheduled reminders ([21666](https://github.com/civicrm/civicrm-core/pull/21666))**
+
+- **MessageTemplate API - Fix saving of templates with workflow_name sans workflow_id ([21694](https://github.com/civicrm/civicrm-core/pull/21694))**
+
+- **[REF] Use getSubmittedValue rather than passed values ([21668](https://github.com/civicrm/civicrm-core/pull/21668))**
+
+- **Another enotice fix ([21682](https://github.com/civicrm/civicrm-core/pull/21682))**
+
+- **And another one ([21683](https://github.com/civicrm/civicrm-core/pull/21683))**
+
+- **Another one bites the dust ([21684](https://github.com/civicrm/civicrm-core/pull/21684))**
+
+- **Rename test clas to reflect tested class name ([21686](https://github.com/civicrm/civicrm-core/pull/21686))**
+
+- **[REF] Extract getRedirectUrl method ([21687](https://github.com/civicrm/civicrm-core/pull/21687))**
+
+- **Remove unused paramter ([21685](https://github.com/civicrm/civicrm-core/pull/21685))**
+
+- **Remove workflow_id reference ([21671](https://github.com/civicrm/civicrm-core/pull/21671))**
+
+- **[NFC] Unit test for file-on-case ([21678](https://github.com/civicrm/civicrm-core/pull/21678))**
+
+- **Remove now-silly function ([21680](https://github.com/civicrm/civicrm-core/pull/21680))**
+
+- **Update SelfSvcUpdate.php ([21679](https://github.com/civicrm/civicrm-core/pull/21679))**
+
+- **Return another function to the email trait ([21677](https://github.com/civicrm/civicrm-core/pull/21677))**
+
+- **[REF] Copy another email trait function back to the trait ([21648](https://github.com/civicrm/civicrm-core/pull/21648))**
+
+- **ContributionRecur modified_date should update to current_timestamp on update ([21472](https://github.com/civicrm/civicrm-core/pull/21472))**
+
+- **(dev/drupal#163) Session erroneously getting set to NULL on change ([21403](https://github.com/civicrm/civicrm-core/pull/21403))**
+
+- **Add message admin to dist ([21670](https://github.com/civicrm/civicrm-core/pull/21670))**
+
+- **Fix header e-notices ([21633](https://github.com/civicrm/civicrm-core/pull/21633))**
+
+- **dev/mail#83 - Import current revision of "Message Admin" ([21590](https://github.com/civicrm/civicrm-core/pull/21590))**
+
+- **Tests -  update to use postProcess ([21637](https://github.com/civicrm/civicrm-core/pull/21637))**
+
+- **Fixed issue with sending from do-not-reply@domain address ([21455](https://github.com/civicrm/civicrm-core/pull/21455))**
+
+- **Basic IDE cleanup on test class ([21661](https://github.com/civicrm/civicrm-core/pull/21661))**
+
+- **Simplify getRecurFromAddress ([21613](https://github.com/civicrm/civicrm-core/pull/21613))**
+
+- **5.42 to master ([21665](https://github.com/civicrm/civicrm-core/pull/21665))**
+
+- **Test fix ([21662](https://github.com/civicrm/civicrm-core/pull/21662))**
+
+- **Remove call to the dreaded replaceMultipleContributionTokens ([21652](https://github.com/civicrm/civicrm-core/pull/21652))**
+
+- **dev/core#2832 Switch membership pdf to use token processor ([21521](https://github.com/civicrm/civicrm-core/pull/21521))**
+
+- **Enotice fix ([21658](https://github.com/civicrm/civicrm-core/pull/21658))**
+
+- **Enotice fixes ([21659](https://github.com/civicrm/civicrm-core/pull/21659))**
+
+- **Find Activities Search, the default search option of "With" criteria excludes Activities by default. Confuses End Users when 0 results are returned when criteria appears to be correct. ([21595](https://github.com/civicrm/civicrm-core/pull/21595))**
+
+- **Do not send email notification to the user if `notify` is not set in the params ([21562](https://github.com/civicrm/civicrm-core/pull/21562))**
+
+- **MessageTemplate - Deprecate `valueName`. Emphasize `workflow`. Consolidate converters.  ([21657](https://github.com/civicrm/civicrm-core/pull/21657))**
+
+- **Fix label for participant role ([21656](https://github.com/civicrm/civicrm-core/pull/21656))**
+
+- **dev/core#2834 Use event tokens for participant badges ([21587](https://github.com/civicrm/civicrm-core/pull/21587))**
+
+- **(REF) MessageTemplate - Reverse renderTemplate()<=>sendTemplate() call ([21610](https://github.com/civicrm/civicrm-core/pull/21610))**
+
+- **dev/core#2126 - Allow setting dompdf options, e.g. an external font folder ([21423](https://github.com/civicrm/civicrm-core/pull/21423))**
+
+- **typo fixes ([21655](https://github.com/civicrm/civicrm-core/pull/21655))**
+
+- **[REF] stop passing form into createActivities ([21653](https://github.com/civicrm/civicrm-core/pull/21653))**
+
+- **tests/events/*.php - Enforce general compliance with hook/event signatures  ([21615](https://github.com/civicrm/civicrm-core/pull/21615))**
+
+- **Set default for civicrm_message_template.is_reserved ([21651](https://github.com/civicrm/civicrm-core/pull/21651))**
+
+- **dev/core#2870 Fix upgrade error with rpow installed ([21640](https://github.com/civicrm/civicrm-core/pull/21640))**
+
+- **APIv4 - Automatically coalesce potentially null field values in equations ([21647](https://github.com/civicrm/civicrm-core/pull/21647))**
+
+- **Extend token date handling to 'most' date fields ([21584](https://github.com/civicrm/civicrm-core/pull/21584))**
+
+- **HttpTestTrait - Allow one to easily authenticate subrequests ([21261](https://github.com/civicrm/civicrm-core/pull/21261))**
+
+- **Fix extra apostrophe added in 21636 ([21650](https://github.com/civicrm/civicrm-core/pull/21650))**
+
+- **Test regression fix ([21649](https://github.com/civicrm/civicrm-core/pull/21649))**
+
+- **avoid back trace when importing preferred communication method ([21433](https://github.com/civicrm/civicrm-core/pull/21433))**
+
+- **Afform - ensure default value data type matches input type ([21643](https://github.com/civicrm/civicrm-core/pull/21643))**
+
+- **Enotice fix ([21636](https://github.com/civicrm/civicrm-core/pull/21636))**
+
+- **Enotice fixes ([21632](https://github.com/civicrm/civicrm-core/pull/21632))**
+
+- **enotice fixes in fatal error template ([21639](https://github.com/civicrm/civicrm-core/pull/21639))**
+
+- **Remove handling for empty required field ([21623](https://github.com/civicrm/civicrm-core/pull/21623))**
+
+- **dev/core#2629 show only contribution statuses on contribution form ([21624](https://github.com/civicrm/civicrm-core/pull/21624))**
+
+- **Remove over-copied function ([21641](https://github.com/civicrm/civicrm-core/pull/21641))**
+
+- **[REF] Separate contact tokens from 'tokenCompatSubscriber' ([21626](https://github.com/civicrm/civicrm-core/pull/21626))**
+
+- **Afform - Accept default field values from the url ([21606](https://github.com/civicrm/civicrm-core/pull/21606))**
+
+- **[REF] Update Frequenecy template assignments in UpdateBilling to be c… ([21635](https://github.com/civicrm/civicrm-core/pull/21635))**
+
+- **Fix dev/core#2867 - APIv4 Entity.get to return class name by default ([21634](https://github.com/civicrm/civicrm-core/pull/21634))**
+
+- **enotice fix ([21631](https://github.com/civicrm/civicrm-core/pull/21631))**
+
+- **Convert more tests to call postProcess ([21628](https://github.com/civicrm/civicrm-core/pull/21628))**
+
+- **SearchKit - Style buttons for compatability with Shoreditch theme ([21627](https://github.com/civicrm/civicrm-core/pull/21627))**
+
+- **Fix test to use postProcess ([21630](https://github.com/civicrm/civicrm-core/pull/21630))**
+
+- **Afform - fix loading embedded blocks ([21609](https://github.com/civicrm/civicrm-core/pull/21609))**
+
+- **Test cleanup -convert to use postProcess ([21629](https://github.com/civicrm/civicrm-core/pull/21629))**
+
+- **Setting::getItem - use deprecatedWarning instead of just logging ([21625](https://github.com/civicrm/civicrm-core/pull/21625))**
+
+- **Test cleanup ([21622](https://github.com/civicrm/civicrm-core/pull/21622))**
+
+- **dev/core#2650 dev/core#2814 Add support for preferred syntax for contact tokens ([21570](https://github.com/civicrm/civicrm-core/pull/21570))**
+
+- **SearchKit - Add UI for arithmetic equations ([21600](https://github.com/civicrm/civicrm-core/pull/21600))**
+
+- ** Add upgrade to replace legacy contribution tokens from message templates ([21605](https://github.com/civicrm/civicrm-core/pull/21605))**
+
+- **SearchKit - A random stable genius ([21586](https://github.com/civicrm/civicrm-core/pull/21586))**
+
+- **Remove unused function - convertDateFieldsToMySQL ([21617](https://github.com/civicrm/civicrm-core/pull/21617))**
+
+- **[Ref] Function signature cleanup ([21618](https://github.com/civicrm/civicrm-core/pull/21618))**
+
+- **5.42 ([21612](https://github.com/civicrm/civicrm-core/pull/21612))**
+
+- **[REF] Return the sendEmail function to it's owner ([21608](https://github.com/civicrm/civicrm-core/pull/21608))**
+
+- **Fix display of subscription frequency on 'Update Subscription' form ([21469](https://github.com/civicrm/civicrm-core/pull/21469))**
+
+- **Remove all references to safe_mode, DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0 ([21594](https://github.com/civicrm/civicrm-core/pull/21594))**
+
+- **Remove broken code ([21602](https://github.com/civicrm/civicrm-core/pull/21602))**
+
+- **dev/core#2851 Fix send email task contribution tokens to the processor ([21565](https://github.com/civicrm/civicrm-core/pull/21565))**
+
+- **Find Activities Search, default search option for Activity Text is set to "both" in the code, but should actually be set to 6 which is the value for "both" ([21598](https://github.com/civicrm/civicrm-core/pull/21598))**
+
+- **Add test to cancel subscription form ([21588](https://github.com/civicrm/civicrm-core/pull/21588))**
+
+- **Fix test ([21585](https://github.com/civicrm/civicrm-core/pull/21585))**
+
+- **Clean up UpdateBilling/UpdateSubscription/ContributionRecur to use getters ([21538](https://github.com/civicrm/civicrm-core/pull/21538))**
+
+- **Fixes dev/core#2824 - Handle related Afforms when deleting Search Displays ([21457](https://github.com/civicrm/civicrm-core/pull/21457))**
+
+- **ensure recur options are present on backend cc contribution form. ([21577](https://github.com/civicrm/civicrm-core/pull/21577))**
+
+- **Add unique class to price field template ([21484](https://github.com/civicrm/civicrm-core/pull/21484))**
+
+- **dev/core#2851 Block use of legacy style contribution tokens ([21525](https://github.com/civicrm/civicrm-core/pull/21525))**
+
+- **dev/core#2856 - Token "filter" can be null so filter[0] doesn't exist ([21580](https://github.com/civicrm/civicrm-core/pull/21580))**
+
+- **dev/core#2814 fix tokenCompat to be consistent with unresolved tokens ([21568](https://github.com/civicrm/civicrm-core/pull/21568))**
+
+- **Enotice fix ([21579](https://github.com/civicrm/civicrm-core/pull/21579))**
+
+- **Fixes dev/core#2852 - Add is_primary as a default SearchKit filter ([21574](https://github.com/civicrm/civicrm-core/pull/21574))**
+
+- **dev/core#2850 update_email_resetdate consider opt out on hold ([21564](https://github.com/civicrm/civicrm-core/pull/21564))**
+
+- **Afform - Add getters/setters to the AfformSubmitEvent class ([21572](https://github.com/civicrm/civicrm-core/pull/21572))**
+
+- **APIv4 - Add support for sql equations ([21551](https://github.com/civicrm/civicrm-core/pull/21551))**
+
+- **CRM_Utils_Date - Month and day names should match active locale ([21569](https://github.com/civicrm/civicrm-core/pull/21569))**
+
+- **Fix bug where log hook is ignored on custom field create ([21557](https://github.com/civicrm/civicrm-core/pull/21557))**
+
+- **Add {domain.now}, supporting |crmDate ([21531](https://github.com/civicrm/civicrm-core/pull/21531))**
+
+- **UFMatch - E_NOTICE when nonexistent uf_id ([21576](https://github.com/civicrm/civicrm-core/pull/21576))**
+
+- **5.42 to master ([21578](https://github.com/civicrm/civicrm-core/pull/21578))**
+
+- **[REF] Remove illusion of looping ([21554](https://github.com/civicrm/civicrm-core/pull/21554))**
+
+- **Initial test on event tokens ([21563](https://github.com/civicrm/civicrm-core/pull/21563))**
+
+- **Remove deprecated code lines ([21566](https://github.com/civicrm/civicrm-core/pull/21566))**
+
+- **dev/core#2493 Add support for money laundry in `getSubmittedValue` ([21555](https://github.com/civicrm/civicrm-core/pull/21555))**
+
+- **flushCaches should respect permitCacheFlushMode. Also flush caches which have a NULL cache_date ([21430](https://github.com/civicrm/civicrm-core/pull/21430))**
+
+- **[Ref] Extend email trait test, process more sanely ([21553](https://github.com/civicrm/civicrm-core/pull/21553))**
+
+- **dev/core#2814 TokenCompatSubscriber - evaluate contact tokens during civi.token.eval phase ([21494](https://github.com/civicrm/civicrm-core/pull/21494))**
+
+- **Fix event custom field tokens in scheduled reminders ([21374](https://github.com/civicrm/civicrm-core/pull/21374))**
+
+- **CiviReport - avoid error in test environments when using built-in php web server ([21560](https://github.com/civicrm/civicrm-core/pull/21560))**
+
+- **5.42 to master ([21561](https://github.com/civicrm/civicrm-core/pull/21561))**
+
+- **Stop testing for gender_id output that was described as 'legacy' years ago ([21558](https://github.com/civicrm/civicrm-core/pull/21558))**
+
+- **Convert event badges to use token processor ([21530](https://github.com/civicrm/civicrm-core/pull/21530))**
+
+- **Participant tokens - remove / replace unsupportable from badges (conversion preparation) ([21520](https://github.com/civicrm/civicrm-core/pull/21520))**
+
+- **Use the processor function to get event tokens ([21537](https://github.com/civicrm/civicrm-core/pull/21537))**
+
+- **Cleanup on test tear downs ([21552](https://github.com/civicrm/civicrm-core/pull/21552))**
+
+- **Missed message template updates from 5.39/5.40 ([21550](https://github.com/civicrm/civicrm-core/pull/21550))**
+
+- **dev/core#2554 Remove code to assign contact to the template in sendEmail ([21490](https://github.com/civicrm/civicrm-core/pull/21490))**
+
+- **dev/core#2820: Deduping produces bad results after a rule change ([21509](https://github.com/civicrm/civicrm-core/pull/21509))**
+
+- **Add support for CiviCRM date formats in crmDate ([21508](https://github.com/civicrm/civicrm-core/pull/21508))**
+
+- **dev/core#2839 Fix addition of _preview to filename ([21493](https://github.com/civicrm/civicrm-core/pull/21493))**
+
+- **View Contribution page, move the Done button to the last button, currently shown in the middle ([21547](https://github.com/civicrm/civicrm-core/pull/21547))**
+
+- **Add test and fix for API4 failing to decode strings stored as HTML ([21549](https://github.com/civicrm/civicrm-core/pull/21549))**
+
+- **Replace "Print Invoice" and "Print Invoice and Credit Note" buttons with label "Download Invoice" and "Download Invoice and Credit Note" ([21546](https://github.com/civicrm/civicrm-core/pull/21546))**
+
+- **SearchKit - Fix in-place edit of relationships and dates ([21533](https://github.com/civicrm/civicrm-core/pull/21533))**
+
+- **Test tearDown fixes ([21548](https://github.com/civicrm/civicrm-core/pull/21548))**
+
+- **Tpl notice fix ([21543](https://github.com/civicrm/civicrm-core/pull/21543))**
+
+- **tpl enotice fixes on extensions page ([21545](https://github.com/civicrm/civicrm-core/pull/21545))**
+
+- **Tpl notice fixes ([21544](https://github.com/civicrm/civicrm-core/pull/21544))**
+
+- **Tpl enotice fixes ([21542](https://github.com/civicrm/civicrm-core/pull/21542))**
+
+- **Enotice fixes in tpls ([21541](https://github.com/civicrm/civicrm-core/pull/21541))**
+
+- **dev/core#2717 Use order api for new membership create in batch ([21152](https://github.com/civicrm/civicrm-core/pull/21152))**
+
+- **Fix PHP notices in contributionrecur tpl ([21526](https://github.com/civicrm/civicrm-core/pull/21526))**
+
+- **dev/core#2843 push new link to the end ([21529](https://github.com/civicrm/civicrm-core/pull/21529))**
+
+- **SearchKit - Exclude custom fields from ON clause selector ([21495](https://github.com/civicrm/civicrm-core/pull/21495))**
+
+- **Add CONCAT_WS fn to APIv4 and UI support in SearchKit ([21535](https://github.com/civicrm/civicrm-core/pull/21535))**
+
+- **[REF] Extract domain tokens to their own class ([21510](https://github.com/civicrm/civicrm-core/pull/21510))**
+
+- **SearchKit - Support multiple arguments to field transformations aka SQL functions ([21528](https://github.com/civicrm/civicrm-core/pull/21528))**
+
+- **Annotate deprecated token functions ([21523](https://github.com/civicrm/civicrm-core/pull/21523))**
+
+- **Update contributors for Third Sector Design ([21516](https://github.com/civicrm/civicrm-core/pull/21516))**
+
+- **Don't clear the GroupContactCache until we're ready to insert the new version ([21384](https://github.com/civicrm/civicrm-core/pull/21384))**
+
+- **dev/core#2832 Extend Membership tokens to 'listen' and add test cover ([21506](https://github.com/civicrm/civicrm-core/pull/21506))**
+
+- **Fix syntax error on a ts() function call ([21518](https://github.com/civicrm/civicrm-core/pull/21518))**
+
+- **5.42 to master ([21515](https://github.com/civicrm/civicrm-core/pull/21515))**
+
+- **Fix activity tokens ([21489](https://github.com/civicrm/civicrm-core/pull/21489))**
+
+- **dev/core#2790 Move rest of pdfCommon functionality to the trait ([21479](https://github.com/civicrm/civicrm-core/pull/21479))**
+
+- **[REF] add test & static array to participant values tokens ([21476](https://github.com/civicrm/civicrm-core/pull/21476))**
+
+- **Add workflow template for 'recurring edit' workflow ([21356](https://github.com/civicrm/civicrm-core/pull/21356))**
+
+- **5.42 to master ([21505](https://github.com/civicrm/civicrm-core/pull/21505))**
+
+- **Attempt to fix test site 500 errors on activity pdf ([21504](https://github.com/civicrm/civicrm-core/pull/21504))**
+
+- **Tpl notice fixes ([21503](https://github.com/civicrm/civicrm-core/pull/21503))**
+
+- **Add sort functionality to event summary report ([21501](https://github.com/civicrm/civicrm-core/pull/21501))**
+
+- **dev/core#2486 Add printLabel v4 api ([21500](https://github.com/civicrm/civicrm-core/pull/21500))**
+
+- **[NFC] [test] minor cleanup in test ([21498](https://github.com/civicrm/civicrm-core/pull/21498))**
+
+- **Revert "dev/core#2812 Fix issue where having a processor configured w… ([21499](https://github.com/civicrm/civicrm-core/pull/21499))**
+
+- **Remove fugly bit ([21497](https://github.com/civicrm/civicrm-core/pull/21497))**
+
+- **5.42 to master ([21496](https://github.com/civicrm/civicrm-core/pull/21496))**
+
+- **dev/core#2814 TokenCompatSubscriber - Evaluate tokens during "civi.token.eval" phase ([21449](https://github.com/civicrm/civicrm-core/pull/21449))**
+
+- **SearchKit - Correctly process filters passed through Afform from js ([21485](https://github.com/civicrm/civicrm-core/pull/21485))**
+
+- **SearchKit - Add pseudo-fields for row number and current user ([21435](https://github.com/civicrm/civicrm-core/pull/21435))**
+
+- **5.42 to master ([21491](https://github.com/civicrm/civicrm-core/pull/21491))**
+
+- **[NFC] Fix Fatal error on php 8 due to mis matched function declaration ([21487](https://github.com/civicrm/civicrm-core/pull/21487))**
+
+- **dev/core#2790 Move pdf postProcess function to the trait ([21478](https://github.com/civicrm/civicrm-core/pull/21478))**
+
+- **dev/core#2817 Remove last core calls to `replaceCaseTokens` ([21447](https://github.com/civicrm/civicrm-core/pull/21447))**
+
+- **(dev/mail#83) EntityTokens - Allow using mocked data ([21486](https://github.com/civicrm/civicrm-core/pull/21486))**
+
+- **SearchKit - Fix links to non-aggregage join fields ([21482](https://github.com/civicrm/civicrm-core/pull/21482))**
+
+- **SearchKit - Fix display of links in aggregated columns ([21420](https://github.com/civicrm/civicrm-core/pull/21420))**
+
+- **[REF] simplify member_tokens ([21481](https://github.com/civicrm/civicrm-core/pull/21481))**
+
+- **(dev/mail#83) ExampleDataLoader - Multiple fixes for quirky examples ([21480](https://github.com/civicrm/civicrm-core/pull/21480))**
+
+- **dev/core#2650 upgrade membership tokens to the new format ([21477](https://github.com/civicrm/civicrm-core/pull/21477))**
+
+- **dev/core#2817 remove call to getTokenDetails ([21475](https://github.com/civicrm/civicrm-core/pull/21475))**
+
+- **fixes core#2318: fix cancel button when sending an individual email ([21474](https://github.com/civicrm/civicrm-core/pull/21474))**
+
+- **dev/core#2650 dev/core#2832 add support & testing for preferred token format ([21464](https://github.com/civicrm/civicrm-core/pull/21464))**
+
+- **flushCaches should respect permitCacheFlushMode ([21468](https://github.com/civicrm/civicrm-core/pull/21468))**
+
+- **dev/core#2817 Use token processor to resolve caseTokens for pdfs ([21445](https://github.com/civicrm/civicrm-core/pull/21445))**
+
+- **[Ref] Cleanup on SelectValues::contributeTokens ([21465](https://github.com/civicrm/civicrm-core/pull/21465))**
+
+- **[Ref] Remove pass-by-reference ([21466](https://github.com/civicrm/civicrm-core/pull/21466))**
+
+- **(dev/mail#83) Introduce WorkflowMessage APIs with CaseActivity example ([21338](https://github.com/civicrm/civicrm-core/pull/21338))**
+
+- **[Ref] Remove unnecessary pass-by-reference ([21463](https://github.com/civicrm/civicrm-core/pull/21463))**
+
+- **dev/core#2834 Preliminary test on badge ([21458](https://github.com/civicrm/civicrm-core/pull/21458))**
+
+- **[REF] Use OO when determining what to suggest for settings.php prefixes for drupal/backdrop views, instead of scattered "if cms ==" ([21042](https://github.com/civicrm/civicrm-core/pull/21042))**
+
+- **[Ref] Remove no-longer-used variables ([21459](https://github.com/civicrm/civicrm-core/pull/21459))**
+
+- **Ensure TokenSmary::render returns an array ([21461](https://github.com/civicrm/civicrm-core/pull/21461))**
+
+- **Afform - gracefully handle missing html files ([21436](https://github.com/civicrm/civicrm-core/pull/21436))**
+
+- **dev/core#2832 Improvements to test on membership letter task ([21452](https://github.com/civicrm/civicrm-core/pull/21452))**
+
+- **5.42 to master ([21460](https://github.com/civicrm/civicrm-core/pull/21460))**
+
+- **APIv4 - Default select clause to exclude "Extra" fields ([21438](https://github.com/civicrm/civicrm-core/pull/21438))**
+
+- **[REF] Remove unused parameter ([21448](https://github.com/civicrm/civicrm-core/pull/21448))**
+
+- **[REF] Remove unused variable ([21451](https://github.com/civicrm/civicrm-core/pull/21451))**
+
+- **[REF] Extract code to load the contact in tokenCompat ([21450](https://github.com/civicrm/civicrm-core/pull/21450))**
+
+- **Authx: README: add note about CMS permissions ([21439](https://github.com/civicrm/civicrm-core/pull/21439))**
+
+- **dev/core#2832 Add test for legacy membership tokens, add support for preferred tokens ([21453](https://github.com/civicrm/civicrm-core/pull/21453))**
+
+- **dev/core#2823 Restructure determination of required actions. ([21401](https://github.com/civicrm/civicrm-core/pull/21401))**
+
+- **Wordpress Profile User Creation Sign On (v2) ([20807](https://github.com/civicrm/civicrm-core/pull/20807))**
+
+- **Consolidate building of contact token list ([21429](https://github.com/civicrm/civicrm-core/pull/21429))**
+
+- **dev/core#2817 Add CaseToken processor ([21383](https://github.com/civicrm/civicrm-core/pull/21383))**
+
+- **dev/core#2829 - "Trying to access array offset on value of type null" on dashboard ([21441](https://github.com/civicrm/civicrm-core/pull/21441))**
+
+- **TokenProcessor - Allow basic filter/modifier expressions ([21428](https://github.com/civicrm/civicrm-core/pull/21428))**
+
+- **dev/core#2823 fix test to be more like real function usage ([21440](https://github.com/civicrm/civicrm-core/pull/21440))**
+
+- **dev/core#2829 - unit test for nonempty dashboard ([21437](https://github.com/civicrm/civicrm-core/pull/21437))**
+
+- **dev/core#2823 Extract code to load the declarations and call from the constructor ([21399](https://github.com/civicrm/civicrm-core/pull/21399))**
+
+- **dev/core#2823 Move validation into validation function ([21400](https://github.com/civicrm/civicrm-core/pull/21400))**
+
+- **dev/core#2828 - Make up for message template text version update from 5.20 that never happened ([21434](https://github.com/civicrm/civicrm-core/pull/21434))**
+
+- **[REF] Move Email, Address, etc. is_primary handling on delete to a hook (dev/core#2757)  ([21211](https://github.com/civicrm/civicrm-core/pull/21211))**
+
+- **SearchKit - Support custom fields in bridge join entities ([21424](https://github.com/civicrm/civicrm-core/pull/21424))**
+
+- **SearchKit - Fix alignment in table headers ([21431](https://github.com/civicrm/civicrm-core/pull/21431))**
+
+- **[REF] Mapping - Check FK on delete with SQL instead of PHP (dev/core#2757) ([21198](https://github.com/civicrm/civicrm-core/pull/21198))**
+
+- **Replace expensive query with cheaper one ([21426](https://github.com/civicrm/civicrm-core/pull/21426))**
+
+- **[REF] Extract function to getDomainTokens ([21416](https://github.com/civicrm/civicrm-core/pull/21416))**
+
+- **Bump minimum upgradable version to 4.5.9 ([21408](https://github.com/civicrm/civicrm-core/pull/21408))**
+
+- **Remove error handling for core error being returned ([21425](https://github.com/civicrm/civicrm-core/pull/21425))**
+
+- **dev/core#2814 Remove redundant call to `replaceContactTokens` ([21414](https://github.com/civicrm/civicrm-core/pull/21414))**
+
+- **Smarty notices on Find Activities results page ([21422](https://github.com/civicrm/civicrm-core/pull/21422))**
+
+- **[REF] Remove cruft ([21418](https://github.com/civicrm/civicrm-core/pull/21418))**
+
+- **Smarty notice on Find Activities / Find Cases ([21421](https://github.com/civicrm/civicrm-core/pull/21421))**
+
+- **Follow up on removing contributeMode from templates ([21417](https://github.com/civicrm/civicrm-core/pull/21417))**
+
+- **Merge 5.42 to master ([21419](https://github.com/civicrm/civicrm-core/pull/21419))**
+
+- **dev/core#2748 Remove unused token assigns ([21059](https://github.com/civicrm/civicrm-core/pull/21059))**
+
+- **dev/core#2823 update function visibility to protected ([21412](https://github.com/civicrm/civicrm-core/pull/21412))**
+
+- **Mailing Unsubscribe Form: Show if email is already unsubscribed ([21174](https://github.com/civicrm/civicrm-core/pull/21174))**
+
+- **Smarty warning about missing contact subtype on New Individual ([21410](https://github.com/civicrm/civicrm-core/pull/21410))**
+
+- **Remove duplicate global declaration in civicrm.settings.php template ([21409](https://github.com/civicrm/civicrm-core/pull/21409))**
+
+- **SearchKit & Afform - Use Bootstrap table styles on admin screens ([21405](https://github.com/civicrm/civicrm-core/pull/21405))**
+
+- **[search kit] Semicolon vs comma ([21406](https://github.com/civicrm/civicrm-core/pull/21406))**
+
+- **Fixes dev/core#2826 SearchKit - Fix delete search confirm dialog ([21404](https://github.com/civicrm/civicrm-core/pull/21404))**
+
+- **SearchKit - Support bootstrap styles in search display tables ([21397](https://github.com/civicrm/civicrm-core/pull/21397))**
+
+- **dev/core#2817 Block submission of pdf with text including token format that is ambiguous with the processor ([21381](https://github.com/civicrm/civicrm-core/pull/21381))**
+
+- **SearchKit - Prevent race conditions in search display loading ([21394](https://github.com/civicrm/civicrm-core/pull/21394))**
+
+- **SearchKit - Filter search listing by creator ([21388](https://github.com/civicrm/civicrm-core/pull/21388))**
+
+- **[NFC] Put back email test without tokens and enhance a little ([21398](https://github.com/civicrm/civicrm-core/pull/21398))**
+
+- **Fix Upgrade step to ensure all fields are converted correctly as well ([21396](https://github.com/civicrm/civicrm-core/pull/21396))**
+
+- **dev/core#2823 Make protected functions non-static ([21395](https://github.com/civicrm/civicrm-core/pull/21395))**
+
+- **Import csv-Fix not importing extension in phones ([20995](https://github.com/civicrm/civicrm-core/pull/20995))**
+
+- **dev/core#2772 - Don't crash for custom fields of type int that are multi-select ([21186](https://github.com/civicrm/civicrm-core/pull/21186))**
+
+- **[REF] Update Product Create to use hooks and also switch the manage p… ([20822](https://github.com/civicrm/civicrm-core/pull/20822))**
+
+- **[REF] Add in upgrade step to align the relationship cache table colla… ([21389](https://github.com/civicrm/civicrm-core/pull/21389))**
+
+- **dev/core#2817 towards deprecating legacy `replaceCaseTokens` ([21380](https://github.com/civicrm/civicrm-core/pull/21380))**
+
+- **[NFC] Extend send email test to cover for contact tokens being replaced ([21386](https://github.com/civicrm/civicrm-core/pull/21386))**
+
+- **[NFC] Add in type hints to template upgrade functions ([21390](https://github.com/civicrm/civicrm-core/pull/21390))**
+
+- **Don't specify character set for civicrm_relationship_cache table ([21382](https://github.com/civicrm/civicrm-core/pull/21382))**
+
+- **dev/core#2814 Fix activity:sendEmail follow up ([21385](https://github.com/civicrm/civicrm-core/pull/21385))**
+
+- **Change Do Not SMS privacy icon ([21354](https://github.com/civicrm/civicrm-core/pull/21354))**
+
+- **dev/core#2814 Fix membership pdf to use renderTemplate ([21379](https://github.com/civicrm/civicrm-core/pull/21379))**
+
+- **dev/core#2793 - Add REGEXP/NOT REGEXP SQL operators ([21288](https://github.com/civicrm/civicrm-core/pull/21288))**
+
+- **Remove requirement to enter email address on Opt Out ([21350](https://github.com/civicrm/civicrm-core/pull/21350))**
+
+- **Remove requirement to enter email address on unsubscribe ([21175](https://github.com/civicrm/civicrm-core/pull/21175))**
+
+- **dev/core#2715 Move 2 more functions to financial processor class ([21370](https://github.com/civicrm/civicrm-core/pull/21370))**
+
+- **[REF] Cleanup BAO::del() functions with unnecessary FK checks (dev/core#2757) ([21199](https://github.com/civicrm/civicrm-core/pull/21199))**
+
+- **dev/core#2814 Fix activity:sendSMS to use renderTemplate ([21377](https://github.com/civicrm/civicrm-core/pull/21377))**
+
+- **dev/core#2814 Fix test to use renderTemplate ([21378](https://github.com/civicrm/civicrm-core/pull/21378))**
+
+- **SearchKit - enable tags for Saved Searches ([21376](https://github.com/civicrm/civicrm-core/pull/21376))**
+
+- **[REF] Extract code to get the from address for a recurring contribution. ([21357](https://github.com/civicrm/civicrm-core/pull/21357))**
+
+- **[REF] dev/core#2790 Move pdf getFileName functionality to the trait ([21366](https://github.com/civicrm/civicrm-core/pull/21366))**
+
+- **dev/core#2814 Fix activity:sendEmail to use renderTemplate ([21365](https://github.com/civicrm/civicrm-core/pull/21365))**
+
+- **dev/core#2814 migrate export processor to use MessageRender ([21367](https://github.com/civicrm/civicrm-core/pull/21367))**
+
+- **dev/core#2814 Fix profile edit to use messagetemplate:render ([21364](https://github.com/civicrm/civicrm-core/pull/21364))**
+
+- **[REF] dev/core#2790 dev/core#2814 Start migration to MessageTemplate::render ([21335](https://github.com/civicrm/civicrm-core/pull/21335))**
+
+- **Fix test to test trait not deprecated function ([21373](https://github.com/civicrm/civicrm-core/pull/21373))**
+
+- **Update use of CRM_Utils_System::setTitle() for legacycustomsearches ([21375](https://github.com/civicrm/civicrm-core/pull/21375))**
+
+- **Switch to CRM_Core_Form::setTitle() instead of CRM_Utils_System::setTitle() part 4 ([21368](https://github.com/civicrm/civicrm-core/pull/21368))**
+
+- **Remove deprecated input variable ([21372](https://github.com/civicrm/civicrm-core/pull/21372))**
+
+- **Remove unused private function ([21371](https://github.com/civicrm/civicrm-core/pull/21371))**
+
+- **dev/translation#71 getFullMonthNames: do not rely on the OS for translation ([21157](https://github.com/civicrm/civicrm-core/pull/21157))**
+
+- **[NFC/Unit test] - Fix secondary issue with case token consistency test ([21369](https://github.com/civicrm/civicrm-core/pull/21369))**
+
+- **Add SqlFunction support in addWhere  ([21301](https://github.com/civicrm/civicrm-core/pull/21301))**
+
+- **SearchKit - Add 'array' option to download API and add test ([21363](https://github.com/civicrm/civicrm-core/pull/21363))**
+
+- **dev/core#2715 [REF] Move another 2 functions to the financial processor class ([20985](https://github.com/civicrm/civicrm-core/pull/20985))**
+
+- **Remove deprecated function ([21361](https://github.com/civicrm/civicrm-core/pull/21361))**
+
+- **[REF] dev/core#2790 Follow on on code move, make not static ([21359](https://github.com/civicrm/civicrm-core/pull/21359))**
+
+- **dev/core#2486 Add survey v4 api ([21355](https://github.com/civicrm/civicrm-core/pull/21355))**
+
+- **Remove testing hack ([21360](https://github.com/civicrm/civicrm-core/pull/21360))**
+
+- **Remove deprecated function ([21358](https://github.com/civicrm/civicrm-core/pull/21358))**
+
+- **[REF] Fix form to call this->setTitle() ([21362](https://github.com/civicrm/civicrm-core/pull/21362))**
+
+- **activity import: prepend custom group title to custom fields ([21318](https://github.com/civicrm/civicrm-core/pull/21318))**
+
+- **[REF] Deprecate 2 del() functions in favor of generics and hooks (dev/core#2757) ([21210](https://github.com/civicrm/civicrm-core/pull/21210))**
+
+- **Switch to CRM_Core_Form::setTitle() instead of CRM_Utils_System::setTitle() part 3 ([21352](https://github.com/civicrm/civicrm-core/pull/21352))**
+
+- **Switch to CRM_Core_Form::setTitle() instead of CRM_Utils_System::setTitle() part 2 ([21202](https://github.com/civicrm/civicrm-core/pull/21202))**
+
+- **NFC Clarify description for ckeditor4 plugin ([21349](https://github.com/civicrm/civicrm-core/pull/21349))**
+
+- **dev/core#2716 [REF] Stop 'distributing' the main flow ([20856](https://github.com/civicrm/civicrm-core/pull/20856))**
+
+- **[REF] Do not set input['line_item'] pointlessly ([21311](https://github.com/civicrm/civicrm-core/pull/21311))**
+
+- **dev/core#1618 Trigger a reconciliation of logging tables after Extens… ([21135](https://github.com/civicrm/civicrm-core/pull/21135))**
+
+- **#13 - Contact Image uploaded from Drupal Webform don't render on Drup… ([524](https://github.com/civicrm/civicrm-drupal/pull/524))**
+
+- **Add deduping to Quick Add Dashboard Widget ([256](https://github.com/civicrm/civicrm-wordpress/pull/256))**
+
+- **Fix generating civicrm.settings.php by ensuring that CMSdbSSL and dbS… ([63](https://github.com/civicrm/civicrm-joomla/pull/63))**
+
+## <a name="misc"></a>Miscellany
+
+## <a name="credits"></a>Credits
+
+This release was developed by the following code authors:
+
+AGH Strategies - Alice Frumin, Andie Hunt; Agileware - Justin Freeman; Andy Burns; Benjamin W; Christian Wach; CiviCoop - Jaap Jansma; CiviCRM - Coleman Watts, Tim Otten; CiviDesk - Yashodha Chaku; Coop SymbioTIC - Mathieu Lutfy; Dave D; Digitalcourage - Detlev Sieber; Francesc Bassas i Bullich; Fuzion - Jitendra Purohit; Greenpeace Central and Eastern Europe - Patrick Figel; iXiam - Rubén Pineda; JMA Consulting - Monish Deb, Seamus Lee; John Kingsnorth; Lighthouse Consulting and Design - Brian Shaughnessy; Megaphone Technology Consulting - Jon Goldberg; MJW Consulting - Matthew Wire; Progressive Technology Project - Jamie McClelland; Third Sector Design - Kurund Jalmi, Michael McAndrew, William Mortada; Valéry Gouleau; Wikimedia Foundation - Eileen McNaughton
+
+Most authors also reviewed code for this release; in addition, the following
+reviewers contributed their comments:
+
+AGH Strategies - Andie Hunt, Eli Lisseck; Agileware - Justin Freeman; Artful Robot - Rich Lott; awestuk; Black Brick Software - David Hayes; Christian Wach; civibot[bot]; CiviCoop - Jaap Jansma; civicrm-builder; CiviCRM - Coleman Watts, Josh Gowans, Tim Otten; CiviDesk - Yashodha Chaku; CompuCorp - Omar Abu Hussein; Coop SymbioTIC - Mathieu Lutfy; Dave D; Francesc Bassas i Bullich; Freeform Solutions - Herb van den Dool; Fuzion - Jitendra Purohit; Greenpeace Central and Eastern Europe - Patrick Figel; JMA Consulting - Monish Deb, Seamus Lee; John Kingsnorth; Lemniscus - Noah Miller; Lighthouse Consulting and Design - Brian Shaughnessy; Megaphone Technology Consulting - Jon Goldberg; MJW Consulting - Matthew Wire; OPEN - dewy; Progressive Technology Project - Jamie McClelland; rbaugh; Richard van Oosterhout; Semper IT - Karin Gerritsen; Skvare - Mark Hanna; Squiffle Consulting - Aidan Saunders; Tadpole Collective - Kevin Cristiano; Third Sector Design - Kurund Jalmi, William Mortada; Wikimedia Foundation - Eileen McNaughton
+
+## <a name="feedback"></a>Feedback
+
+These release notes are edited by Alice Frumin and Andie Hunt.  If you'd like
+to provide feedback on them, please log in to https://chat.civicrm.org/civicrm
+and contact `@agh1`.
+
diff --git a/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php b/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php
index fa2a50b8dbc95ca0293b8c97ba6e51c6937a6800..44c47552be1686495ef12a9bbb6b7a5c922f2791 100644
--- a/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php
+++ b/tests/phpunit/CRM/Contribute/ActionMapping/ByTypeTest.php
@@ -311,10 +311,10 @@ class CRM_Contribute_ActionMapping_ByTypeTest extends \Civi\ActionSchedule\Abstr
       'payment instrument id = 4',
       'payment instrument name = Check',
       'payment instrument label = Check',
-      'non_deductible_amount = € 10.00',
-      'total_amount = € 100.00',
-      'net_amount = € 95.00',
-      'fee_amount = € 5.00',
+      'non_deductible_amount = €10.00',
+      'total_amount = €100.00',
+      'net_amount = €95.00',
+      'fee_amount = €5.00',
       'campaign_id = 1',
       'campaign name = big_campaign',
       'campaign label = Campaign',
diff --git a/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php b/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php
index e3cdc9ffc7efe5b7e5ad8dc1230a3ce4ec073fb3..8211eae5a628b46235efc02843042ac394d903d6 100644
--- a/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php
+++ b/tests/phpunit/CRM/Contribute/Form/Task/EmailTest.php
@@ -70,10 +70,10 @@ class CRM_Contribute_Form_Task_EmailTest extends CiviUnitTestCase {
     $form->buildForm();
     $this->assertEquals('<br/><br/>--Benny, Benny', $form->_defaultValues['html_message']);
     $form->postProcess();
-    $mut->assertSubjects(['Mr. Anthony Anderson II $ 999.00', 'Mr. Elton Anderson II $ 100.00']);
+    $mut->assertSubjects(['Mr. Anthony Anderson II $999.00', 'Mr. Elton Anderson II $100.00']);
     $mut->checkAllMailLog([
       'Subject: Mr. Anthony Anderson II',
-      '$ 999.0',
+      '$999.0',
       'Default Domain Name',
       'Donation soy',
       'Donation ranch',
diff --git a/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php b/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php
index 54250b806d731f3e268642b7cea8f4b8b0725934..91e06ed8fb4b8e70ba60a644257b891f90119c21 100644
--- a/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php
+++ b/tests/phpunit/CRM/Contribute/Form/Task/PDFLetterCommonTest.php
@@ -105,7 +105,7 @@ class CRM_Contribute_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase {
       $form->postProcess();
     }
     catch (CRM_Core_Exception_PrematureExitException $e) {
-      $this->assertStringContainsString('USD, USD * $ 60.00, $ 70.00 * January 1st, 2021  1:21 PM, February 1st, 2021  2:21 AM', $e->errorData['html']);
+      $this->assertStringContainsString('USD, USD * $60.00, $70.00 * January 1st, 2021  1:21 PM, February 1st, 2021  2:21 AM', $e->errorData['html']);
     }
   }
 
@@ -198,7 +198,6 @@ class CRM_Contribute_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase {
     $this->createLoggedInUser();;
     foreach (['docx', 'odt'] as $docType) {
       $formValues = [
-        'is_unit_test' => TRUE,
         'group_by' => NULL,
         'document_file' => [
           'name' => __DIR__ . "/sample_documents/Template.$docType",
@@ -297,10 +296,10 @@ class CRM_Contribute_Form_Task_PDFLetterCommonTest extends CiviUnitTestCase {
   <body>
     <div id="crm-container">
 id : 1
-total_amount : &euro; 9,999.99
-fee_amount : &euro; 1,111.11
-net_amount : &euro; 7,777.78
-non_deductible_amount : &euro; 2,222.22
+total_amount : €9,999.99
+fee_amount : €1,111.11
+net_amount : €7,777.78
+non_deductible_amount : €2,222.22
 receive_date : July 20th, 2018
 payment_instrument_id:label : Check
 trxn_id : 1234
diff --git a/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php b/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php
index d758acedfe470ea72b7be96d0eac7fc74fb5d2fd..7cb3d3ee529faf26c8b0b0abb86fb78f97fd1ae7 100644
--- a/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php
+++ b/tests/phpunit/CRM/Contribute/Form/UpdateSubscriptionTest.php
@@ -50,7 +50,7 @@ class CRM_Contribute_Form_UpdateSubscriptionTest extends CRM_Contribute_Form_Rec
       'Return-Path: bob@example.org',
       'Dear Anthony,',
       'Your recurring contribution has been updated as requested:',
-      'Recurring contribution is for $ 10.00, every 1 month(s) for 12 installments.',
+      'Recurring contribution is for $10.00, every 1 month(s) for 12 installments.',
       'If you have questions please contact us at "Bob" <bob@example.org>.',
     ];
   }
diff --git a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php
index e5878ab7848e99c2ddd13388c07c5821a3f8f964..1fe92bae983a11c290bf96dd72c682fe0747ef86 100644
--- a/tests/phpunit/CRM/Utils/TokenConsistencyTest.php
+++ b/tests/phpunit/CRM/Utils/TokenConsistencyTest.php
@@ -47,6 +47,7 @@ class CRM_Utils_TokenConsistencyTest extends CiviUnitTestCase {
    */
   public function tearDown(): void {
     $this->quickCleanup(['civicrm_case', 'civicrm_case_type', 'civicrm_participant', 'civicrm_event'], TRUE);
+    $this->quickCleanUpFinancialEntities();
     parent::tearDown();
   }
 
@@ -206,6 +207,28 @@ case.custom_1 :' . '
     $this->assertEquals($this->getExpectedContributionRecurTokenOutPut(), $tokenProcessor->getRow(0)->render('html'));
   }
 
+  /**
+   * Test money format tokens can respect passed in locale.
+   */
+  public function testMoneyFormat(): void {
+    // Our 'migration' off configured thousand separators at the moment is a define.
+    putenv('IGNORE_SEPARATOR_CONFIG=1');
+    $this->createLoggedInUser();
+    $tokenProcessor = new TokenProcessor(\Civi::dispatcher(), [
+      'controller' => __CLASS__,
+      'smarty' => FALSE,
+      'schema' => ['contribution_recurId'],
+    ]);
+    $tokenString = '{contribution_recur.amount}';
+    $tokenProcessor->addMessage('html', $tokenString, 'text/plain');
+    $tokenProcessor->addRow([
+      'contribution_recurId' => $this->getContributionRecurID(),
+      'locale' => 'nb_NO',
+    ]);
+    $tokenProcessor->evaluate();
+    $this->assertEquals('€ 5 990,99', $tokenProcessor->getRow(0)->render('html'));
+  }
+
   /**
    * Get tokens that are not advertised via listTokens.
    *
@@ -379,7 +402,7 @@ case.custom_1 :' . '
    */
   protected function getExpectedContributionRecurTokenOutPut(): string {
     return 'contribution_recur.id :' . $this->getContributionRecurID() . '
-contribution_recur.amount :€ 5,990.99
+contribution_recur.amount :€5,990.99
 contribution_recur.currency :EUR
 contribution_recur.frequency_unit :year
 contribution_recur.frequency_interval :2
@@ -533,7 +556,7 @@ participant.role_id :1
 participant.register_date :February 19th, 2007
 participant.source :Wimbeldon
 participant.fee_level :steep
-participant.fee_amount :$ 50.00
+participant.fee_amount :$50.00
 participant.registered_by_id :
 participant.transferred_to_contact_id :
 participant.role_id:label :Attendee
diff --git a/tests/phpunit/api/v3/MembershipTest.php b/tests/phpunit/api/v3/MembershipTest.php
index e9c0cdb1582a7a2bd7dc8f47c7f9bb508fb8a349..31f06d7c901e10b18cb7564bca2597c3ddf5c548 100644
--- a/tests/phpunit/api/v3/MembershipTest.php
+++ b/tests/phpunit/api/v3/MembershipTest.php
@@ -843,12 +843,33 @@ class api_v3_MembershipTest extends CiviUnitTestCase {
   ///////////////// civicrm_membership_create methods
 
   /**
-   * Test civicrm_contact_memberships_create with empty params.
-   * Error expected.
+   * Test dates are calculated for pending membership.
    */
-  public function testCreateWithEmptyParams() {
-    $params = [];
-    $this->callAPIFailure('membership', 'create', $params);
+  public function testCreatePending(): void {
+    $membership = $this->callAPISuccess('Membership', 'create', [
+      'contact_id' => $this->individualCreate(),
+      'membership_type_id' => 'General',
+      'status_id' => 'Pending',
+      'sequential' => 1,
+    ])['values'][0];
+    $this->assertEquals(date('Ymd'), $membership['start_date']);
+    $this->assertEquals(date('Ymd', strtotime('+1 year -1 day')), $membership['end_date']);
+  }
+
+  /**
+   * Test dates are calculated for pending membership.
+   */
+  public function testCreatePendingWithSkipStatusCalc(): void {
+    $membership = $this->callAPISuccess('Membership', 'create', [
+      'contact_id' => $this->individualCreate(),
+      'membership_type_id' => 'General',
+      'status_id' => 'Pending',
+      'sequential' => 1,
+      'skipStatusCal' => TRUE,
+    ])['values'][0];
+    $this->assertEquals(date('Ymd'), $membership['start_date']);
+    $this->assertEquals(date('Ymd'), $membership['join_date']);
+    $this->assertEquals(date('Ymd', strtotime('+1 year -1 day')), $membership['end_date']);
   }
 
   /**
diff --git a/tests/phpunit/api/v3/OrderTest.php b/tests/phpunit/api/v3/OrderTest.php
index f8ff93c9ab892c83e24a4a1e6d0eaa0837b3792a..fc76ba033cd35b5ec874630f17b6f0504b251f2e 100644
--- a/tests/phpunit/api/v3/OrderTest.php
+++ b/tests/phpunit/api/v3/OrderTest.php
@@ -316,6 +316,141 @@ class api_v3_OrderTest extends CiviUnitTestCase {
     ]);
   }
 
+  /**
+   * Test create order api for membership, allowing BAO to calculate dates.
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function testAddOrderForMembershipAutoDates(): void {
+    $membershipType = $this->membershipTypeCreate();
+    $p = [
+      'contact_id' => $this->_individualId,
+      'financial_type_id' => 'Member Dues',
+      'contribution_status_id' => 'Pending',
+    ];
+    $priceFields = $this->createPriceSet();
+    foreach ($priceFields['values'] as $key => $priceField) {
+      $lineItems[$key] = [
+        'price_field_id' => $priceField['price_field_id'],
+        'price_field_value_id' => $priceField['id'],
+        'label' => $priceField['label'],
+        'field_title' => $priceField['label'],
+        'qty' => 1,
+        'unit_price' => $priceField['amount'],
+        'line_total' => $priceField['amount'],
+        'financial_type_id' => $priceField['financial_type_id'],
+        'entity_table' => 'civicrm_membership',
+        'membership_type_id' => $membershipType,
+      ];
+    }
+    $p['line_items'][] = [
+      'line_item' => [array_pop($lineItems)],
+      'params' => [
+        'contact_id' => $this->_individualId,
+        'membership_type_id' => $membershipType,
+        'source' => 'Payment',
+      ],
+    ];
+
+    // Create expected dates immediately before order creation to minimise chance of day changing over.
+    $expectedStart = date('Y-m-d');
+    $expectedEnd = date('Y-m-d', strtotime('+ 1 year - 1 day'));
+
+    $order = $this->callAPISuccess('Order', 'create', $p, __FUNCTION__, __FILE__);
+
+    $params = [
+      'id' => $order['id'],
+    ];
+    $order = $this->callAPISuccess('Order', 'get', $params);
+    $expectedResult = [
+      $order['id'] => [
+        'total_amount' => 200,
+        'contribution_id' => $order['id'],
+        'contribution_status' => 'Pending Label**',
+        'net_amount' => 200,
+      ],
+    ];
+    $this->checkPaymentResult($order, $expectedResult);
+
+    $membershipPayment = $this->callAPISuccessGetSingle('MembershipPayment', $params);
+    $membership = $this->callAPISuccessGetSingle('Membership', ['id' => $membershipPayment['id']]);
+
+    // Check membership dates automatically added for legacy skipStatusCal
+    $this->assertEquals($expectedStart, $membership['join_date'] ?? NULL, 'join_date is calculated');
+    $this->assertEquals($expectedStart, $membership['start_date'] ?? NULL, 'start_date is calculated');
+    $this->assertEquals($expectedEnd, $membership['end_date'] ?? NULL, 'end_date is calculated');
+
+    $this->callAPISuccess('Contribution', 'Delete', ['id' => $order['id']]);
+  }
+
+  /**
+   * Test create order api for membership, allowing BAO to calculate dates; skipStatusCal is set but should be ignored.
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function testAddOrderForMembershipAutoDatesSkipStatusCal(): void {
+    $membershipType = $this->membershipTypeCreate();
+    $p = [
+      'contact_id' => $this->_individualId,
+      'financial_type_id' => 'Member Dues',
+      'contribution_status_id' => 'Pending',
+    ];
+    $priceFields = $this->createPriceSet();
+    foreach ($priceFields['values'] as $key => $priceField) {
+      $lineItems[$key] = [
+        'price_field_id' => $priceField['price_field_id'],
+        'price_field_value_id' => $priceField['id'],
+        'label' => $priceField['label'],
+        'field_title' => $priceField['label'],
+        'qty' => 1,
+        'unit_price' => $priceField['amount'],
+        'line_total' => $priceField['amount'],
+        'financial_type_id' => $priceField['financial_type_id'],
+        'entity_table' => 'civicrm_membership',
+        'membership_type_id' => $membershipType,
+      ];
+    }
+    $p['line_items'][] = [
+      'line_item' => [array_pop($lineItems)],
+      'params' => [
+        'contact_id' => $this->_individualId,
+        'membership_type_id' => $membershipType,
+        'source' => 'Payment',
+        'skipStatusCal' => 1,
+      ],
+    ];
+
+    // Create expected dates immediately before order creation to minimise chance of day changing over.
+    $expectedStart = date('Y-m-d');
+    $expectedEnd = date('Y-m-d', strtotime('+ 1 year - 1 day'));
+
+    $order = $this->callAPISuccess('Order', 'create', $p, __FUNCTION__, __FILE__);
+
+    $params = [
+      'id' => $order['id'],
+    ];
+    $order = $this->callAPISuccess('Order', 'get', $params);
+    $expectedResult = [
+      $order['id'] => [
+        'total_amount' => 200,
+        'contribution_id' => $order['id'],
+        'contribution_status' => 'Pending Label**',
+        'net_amount' => 200,
+      ],
+    ];
+    $this->checkPaymentResult($order, $expectedResult);
+
+    $membershipPayment = $this->callAPISuccessGetSingle('MembershipPayment', $params);
+    $membership = $this->callAPISuccessGetSingle('Membership', ['id' => $membershipPayment['id']]);
+
+    // Check membership dates automatically added for legacy skipStatusCal
+    $this->assertEquals($expectedStart, $membership['join_date'] ?? NULL, 'join_date is calculated');
+    $this->assertEquals($expectedStart, $membership['start_date'] ?? NULL, 'start_date is calculated');
+    $this->assertEquals($expectedEnd, $membership['end_date'] ?? NULL, 'end_date is calculated');
+
+    $this->callAPISuccess('Contribution', 'Delete', ['id' => $order['id']]);
+  }
+
   /**
    * Test create order api for participant
    *